audioservice: unified socket interfaces for cast lite transport [1/1]

PD#SWPL-131887

Problem:
1.the server-side program currently in use is based on c++, and needs to be
changed to be based on c for the sake of generality.
2.cast lite based on socket communication between client and server using the
interface is still mainly avs interface, which is not a common interface, so
it should be abstracted into a common interface;
3.lack of server-side demo
4.the original server logic is unable to mass message all clients that
register for the same type of event (cause the map that registers the
message can only be associated with one client at a time)
5.solve the problem of program crash caused by duplicate connect in the
original client code;
6.dynamic libraries add aml log printing.

Solution:
1.rewrite the server related code into c and also write a server and client
test set.
2.the relevant interfaces are updated from the avs directory to the /amlogic/
aml_commonlib directory to further abstract the relevant interfaces;
3.assign a bitmap to each client socket to solve problem 4;
4.using a mutex lock on the thread that calls the connect initialization action

Verify:
A5.

Change-Id: I449d5362571a34a34914f9e003b71b4f9dc482de
Signed-off-by: yifan.li <yifan.li@amlogic.com>
diff --git a/aml_socketipc_v2/Makefile b/aml_socketipc_v2/Makefile
new file mode 100644
index 0000000..f13e757
--- /dev/null
+++ b/aml_socketipc_v2/Makefile
@@ -0,0 +1,24 @@
+CFLAGS += -Wall -g -I../aml_log
+LDFLAGS += -L../aml_log
+LDLIBS += -laml_log
+
+SRC_DIR = common
+SRC = $(SRC_DIR)/util_list.c $(SRC_DIR)/socket_client.c $(SRC_DIR)/socket_server.c $(SRC_DIR)/socket_util.c
+TARGET = libaml_socketipc_v2.so
+
+all: $(TARGET)
+
+$(TARGET): $(SRC)
+	$(CC) $(CFLAGS) $(LDFLAGS) -shared -fPIC \
+	-o $@ $^ $(LDLIBS)
+
+clean:
+	rm $(TARGET)
+
+install:
+	install -m 0644 libaml_socketipc_v2.so $(TARGET_DIR)/usr/lib/
+	install -m 0644 common/*.h $(STAGING_DIR)/usr/include/
+	install -m 0644 libaml_socketipc_v2.so $(STAGING_DIR)/usr/lib/
+
+uninstall:
+	rm -f $(TARGET_DIR)/usr/lib/libaml_socketipc_v2.so
\ No newline at end of file
diff --git a/aml_socketipc_v2/client/Makefile b/aml_socketipc_v2/client/Makefile
new file mode 100644
index 0000000..88080a9
--- /dev/null
+++ b/aml_socketipc_v2/client/Makefile
@@ -0,0 +1,28 @@
+# linux envs
+CC = gcc
+
+CFLAGS = -I. -I../common -pthread -g
+LDFLAGS = -L..
+# Assuming the .so file is in the .. directory. Adjust as necessary.
+# when run, need export LD_LIBRARY_PATH=..:$LD_LIBRARY_PATH
+# or install default lib
+
+SRCS = TestClient.c
+OBJS = $(SRCS:.c=.o)
+
+TARGET = client
+LIBS = -laml_socketipc_v2 -laml_log
+
+.PHONY: all clean
+
+all: $(TARGET)
+	rm -f $(OBJS)
+
+$(TARGET): $(OBJS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $(TARGET)
+
+.c.o:
+	$(CC) $(CFLAGS) -c $< -o $@
+
+clean:
+	rm -f $(OBJS) $(TARGET)
diff --git a/aml_socketipc_v2/client/TestClient.c b/aml_socketipc_v2/client/TestClient.c
new file mode 100644
index 0000000..742ec49
--- /dev/null
+++ b/aml_socketipc_v2/client/TestClient.c
@@ -0,0 +1,255 @@
+// Copyright (C) 2023 Amlogic, Inc. All rights reserved.
+//
+// All information contained herein is Amlogic confidential.
+//
+// This software is provided to you pursuant to Software License
+// Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be
+// used only in accordance with the terms of this agreement.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification is strictly prohibited without prior written permission
+// from Amlogic.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+#include "socket_client.h"
+
+//This is a demo about how to use client api
+/*
+    **************************************************************
+    Defining business data
+    **************************************************************
+*/
+
+enum ServerMsgType {
+    SERVERMSGTYPE1,
+    SERVERMSGTYPE2,
+    SERVERMSGTYPE3,
+    //...... other type message
+
+    MAXServerMsg
+};
+
+enum ServerMsgType2 {
+    SERVERMSGTYPE2VALUE1,
+    SERVERMSGTYPE2VALUE2
+};
+
+typedef struct ServerMsg {
+    enum ServerMsgType type;
+    union {
+        int serverMsgType1Value;
+        enum ServerMsgType2 serverMsgType2Value;
+        float serverMsgType3Value;
+        //...... other message's arguments
+    } u;
+} ServerMsgT;
+
+enum ClientMsgType {
+    CLIENTMSGTYPE1,
+    CLIENTMSGTYPE2,
+    //...... other type message
+
+    MAXClientMsg
+};
+
+enum ClientMsgType2 {
+    CLIENTMSGTYPE2VALUE1,
+    CLIENTMSGTYPE2VALUE2
+};
+
+typedef struct ClientMsg {
+    enum ClientMsgType type;
+    union {
+        int clientMsgType1Value;
+        enum ClientMsgType2 clientMsgType2Value;
+        //...... other message's arguments
+    } u;
+} ClientMsgT;
+/*
+    **************************************************************
+    Defining business data finish
+    **************************************************************
+*/
+
+typedef void (*ServerMsgHandler)(ServerMsgT*);
+extern ClientSocketData clientSocketData;
+ServerMsgHandler msgCbks[MAXServerMsg];
+
+// 1.callback function
+void handleServerMsgAction(char* buf);
+
+// 2.business action functions for sending to server
+void sendClientMsgType1(int msgTypeValue);
+void sendClientMsgType2(enum ClientMsgType2 msgTypeValue);
+
+// 3.business action functions for receiving server message
+void serverMsgType1ActHandle(ServerMsgT* msg);
+void serverMsgType2ActHandle(ServerMsgT* msg);
+void serverMsgType3ActHandle(ServerMsgT* msg);
+
+// 4.Registration and initialization related parameters
+int clientRegisterServerMsgType(enum ServerMsgType* types, ServerMsgHandler* cbks, int num);
+void initializeClientInputData(ClientInputData* clientInputData, char* connectIp, int connectPort, int bitmap);
+
+/*
+    *******************************************************
+    Specific function definitions
+    *******************************************************
+*/
+
+void handleServerMsgAction(char* buf) {
+     // Change the current state based on the type of server message received
+    ServerMsgT *msg = (ServerMsgT *)buf;
+    if (msg->type == SERVERMSGTYPE1) {
+        msgCbks[msg->type](msg);
+    } else if (msg->type == SERVERMSGTYPE2) {
+        msgCbks[msg->type](msg);
+    } else if (msg->type == SERVERMSGTYPE3) {
+        msgCbks[msg->type](msg);
+    }
+}
+
+void serverMsgType1ActHandle(ServerMsgT* msg)
+{
+    printf("receive server MsgType1, value is %d \n", msg->u.serverMsgType1Value);
+}
+
+void serverMsgType2ActHandle(ServerMsgT* msg)
+{
+    printf("receive server MsgType2, value is %d \n", msg->u.serverMsgType2Value);
+}
+
+void serverMsgType3ActHandle(ServerMsgT* msg)
+{
+    printf("receive server MsgType3, value is %f \n", msg->u.serverMsgType3Value);
+}
+
+void sendClientMsgType1(int msgTypeValue)
+{
+    ClientMsgT msg;
+    msg.type = CLIENTMSGTYPE1;
+    msg.u.clientMsgType1Value = msgTypeValue;
+
+    printf("send client MsgType1 to server, value is %d \n", msgTypeValue);
+    ClientWriteMsg2Server(BUSINESS_DATA, &msg, sizeof(msg));
+}
+
+void sendClientMsgType2(enum ClientMsgType2 msgTypeValue)
+{
+    ClientMsgT msg;
+    msg.type = CLIENTMSGTYPE2;
+    msg.u.clientMsgType1Value = msgTypeValue;
+    printf("send client MsgType2 to server, value is %d \n", msgTypeValue);
+
+    ClientWriteMsg2Server(BUSINESS_DATA, &msg, sizeof(msg));
+}
+
+// Register the message type with the server, which may be different for different clients
+int clientRegisterServerMsgType(enum ServerMsgType* types, ServerMsgHandler* cbks, int num)
+{
+    printf("in ClientRegisterServerMsgType\n");
+    int bitmap = 0;
+    for (int i = 0; i < num; i++) {
+        if (types[i] > MAXServerMsg) {
+            printf("ClientRegisterServerMsgType error, invalid ServerMsgType\n");
+            exit(-1);
+        }
+        printf("client register types[i] = %d\n", types[i]);
+        msgCbks[types[i]] = cbks[i];
+        bitmap |= 1 << types[i];
+    }
+    printf("bitmap value is:%d\n", bitmap);
+
+    return bitmap;
+}
+
+// Required, otherwise there are too many parameters
+void initializeClientInputData(ClientInputData* clientInputData, char* connectIp, int connectPort, int bitmap)
+{
+
+    clientInputData->connectIp = connectIp;
+    clientInputData->connectPort = connectPort;
+
+    clientInputData->registerBitmap = bitmap;
+
+    clientInputData->clientHandler = handleServerMsgAction;
+}
+
+int main(int argc, char *argv[])
+{
+/*     // register 3 event
+    enum ServerMsgType types[] = {SERVERMSGTYPE1, SERVERMSGTYPE2, SERVERMSGTYPE3};
+    ServerMsgHandler cbks[]= {serverMsgType1ActHandle, serverMsgType2ActHandle, serverMsgType3ActHandle};
+    int bitmap = clientRegisterServerMsgType(types, cbks, sizeof(cbks)/sizeof(ServerMsgHandler)); */
+
+
+    // register 2 event
+    enum ServerMsgType types[] = {SERVERMSGTYPE1, SERVERMSGTYPE2};
+    ServerMsgHandler cbks[]= {serverMsgType1ActHandle, serverMsgType2ActHandle};
+    int bitmap = clientRegisterServerMsgType(types, cbks, sizeof(cbks)/sizeof(ServerMsgHandler));
+
+
+/*     // register 1 event
+    enum ServerMsgType types[] = {SERVERMSGTYPE1};
+    ServerMsgHandler cbks[]= {serverMsgType1ActHandle};
+    int bitmap = clientRegisterServerMsgType(types, cbks, sizeof(cbks)/sizeof(ServerMsgHandler));
+ */
+    ClientInputData clientInputData;
+    initializeClientInputData(&clientInputData, DEFAULT_IP, DEFAULT_PORT, bitmap);
+    ClientInit(&clientInputData);
+    printf("----------------finsh initialize------------------\n");
+
+    int msgType = -1;
+    int value = -1;
+    while (1) {
+        /*
+        Client sends command simulation
+        clientMsgType1 cmd "1":
+        enter int value:
+
+        clientMsgType2 cmd "2":
+        enter int value:
+        */
+        printf("please enter the msgtype 1-2: ");
+        printf("\n");
+        scanf("%d", &msgType);
+        printf("\n");
+        if (1 == msgType) {
+
+            printf("please input msgtype1 value: ");
+            scanf("%d", &value);
+            printf("\n");
+            sendClientMsgType1(value);
+
+        } else if (2 == msgType) {
+            printf("please input msgtype2 value 0-1: ");
+            scanf("%d", &value);
+            printf("\n");
+            sendClientMsgType2(value);
+        }
+
+        usleep(500 * 1000);
+        msgType = -1;
+        value = -1;
+        printf("\n");
+    }
+
+    ClientExit();
+
+    return 0;
+}
diff --git a/aml_socketipc_v2/common/socket_client.c b/aml_socketipc_v2/common/socket_client.c
new file mode 100644
index 0000000..990a4cf
--- /dev/null
+++ b/aml_socketipc_v2/common/socket_client.c
@@ -0,0 +1,190 @@
+// Copyright (C) 2023 Amlogic, Inc. All rights reserved.
+//
+// All information contained herein is Amlogic confidential.
+//
+// This software is provided to you pursuant to Software License
+// Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be
+// used only in accordance with the terms of this agreement.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification is strictly prohibited without prior written permission
+// from Amlogic.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+#include <errno.h>
+#include <stdbool.h>
+#include "socket_client.h"
+
+#include "aml_log.h"
+
+ClientSocketData clientSocketData;
+
+int ClientWriteMsg2Server(MessageType msgType, void* msg, const int msgLength) {
+    if (BUSINESS_DATA != msgType && REGISTER != msgType) {
+        AML_LOGW("Invalid message type, please send business data......\n");
+        return -1;
+    }
+    MsgHeader header;
+    int totalSize = 0;
+
+    header.type = msgType;
+    header.dataLength = msgLength;
+    totalSize = sizeof(header) + header.dataLength;
+    char buffer[totalSize];
+    memcpy(buffer, &header, sizeof(header));
+    memcpy(buffer + sizeof(header), msg, header.dataLength);
+
+    pthread_mutex_lock(&clientSocketData.writeMsgMutex);
+    int sent_len = writen(clientSocketData.sockfd, buffer, totalSize);
+    pthread_mutex_unlock(&clientSocketData.writeMsgMutex);
+    if (sent_len != totalSize)
+        AML_LOGW("Invalid message type, please send business data......\n");
+    return sent_len;
+}
+
+void register2Server(void)
+{
+    AML_LOGI("in register2Server......\n");
+    int msgLength = sizeof(clientSocketData.registerBitmap);
+    char msg[10];
+    sprintf(msg, "%d", clientSocketData.registerBitmap);
+    int len = ClientWriteMsg2Server(REGISTER, msg, msgLength);
+    if (len == msgLength + sizeof(MsgHeader)) {
+        AML_LOGI("register server message succeed......\n");
+    } else {
+        AML_LOGE("register server message failed......\n");
+        exit(-1);
+    }
+}
+
+void* msgDispatchWorker(void* arg)
+{
+    AML_LOGI("msgDispatchWorker begin work......\n");
+
+    while (1) {
+        // get header message part
+        MsgHeader header;
+        int length = sizeof(header);
+        int n = readn(clientSocketData.sockfd, &header, length);
+        if (n != length) {
+            if (0 == n) {
+                AML_LOGW("Disconnected with server, about to reconnect......\n");
+                pthread_mutex_lock(&clientSocketData.beatMutex);
+                close(clientSocketData.sockfd);
+                initConnection(&clientSocketData.sockfd, clientSocketData.connectIp, clientSocketData.connectPort);
+                register2Server();
+                pthread_mutex_unlock(&clientSocketData.beatMutex);
+            }
+            continue;
+        }
+
+        // get business message part
+        MessageType type = header.type;
+        int dataLength = header.dataLength;
+        if (type == BUSINESS_DATA) {
+            char businessData[8];
+            int n = readn(clientSocketData.sockfd, businessData, 8);
+            if (n != dataLength) {
+                if (n == 0) {
+                    // Connection closed by the server, need to reconnect
+
+                    pthread_mutex_lock(&clientSocketData.beatMutex);
+                    close(clientSocketData.sockfd);
+                    initConnection(&clientSocketData.sockfd, clientSocketData.connectIp, clientSocketData.connectPort);
+                    register2Server();
+                    pthread_mutex_unlock(&clientSocketData.beatMutex);
+                }
+                continue;
+            }
+            AML_LOGD("receive server business message......\n");
+            clientSocketData.clientHandler(businessData);
+        } else if (type == HEARTBEAT) {
+            pthread_mutex_lock(&clientSocketData.beatMutex);
+            clientSocketData.beats = 0;
+            AML_LOGD("receive server heart message......\n");
+            pthread_mutex_unlock(&clientSocketData.beatMutex);
+        }
+    }
+}
+
+void* heartBeatDetectWorker(void* arg)
+{
+    while (1) {
+        pthread_mutex_lock(&clientSocketData.beatMutex);
+        if (clientSocketData.beats > 30) {
+            AML_LOGW("Disconnected with server because of the heartbeat timeout., about to reconnect......\n");
+            close(clientSocketData.sockfd);
+            initConnection(&clientSocketData.sockfd, clientSocketData.connectIp, clientSocketData.connectPort);
+            register2Server();
+        } else {
+            clientSocketData.beats += 10;
+        }
+        pthread_mutex_unlock(&clientSocketData.beatMutex);
+        sleep(10);
+    }
+}
+
+void initClientData(ClientSocketData* clientSocketData, ClientInputData* clientInputData) {
+    if (!clientSocketData || !clientInputData) {
+        AML_LOGE("Null pointer passed to initClientData......\n");
+        return;
+    }
+
+    clientSocketData->sockfd = -1;
+    clientSocketData->beats = 0;
+
+    clientSocketData->connectIp = clientInputData->connectIp;
+    clientSocketData->connectPort = clientInputData->connectPort;
+    clientSocketData->registerBitmap = clientInputData->registerBitmap;
+
+    pthread_mutex_init(&clientSocketData->beatMutex, NULL);
+    pthread_mutex_init(&clientSocketData->writeMsgMutex, NULL);
+
+    clientSocketData->dispatch = 0;
+    clientSocketData->clientHandler = clientInputData->clientHandler;
+}
+
+void ClientInit(ClientInputData* clientInputData)
+{
+    initClientData(&clientSocketData, clientInputData);
+    initConnection(&clientSocketData.sockfd, clientSocketData.connectIp, clientSocketData.connectPort);
+    register2Server();
+    int ret = pthread_create(&clientSocketData.dispatch, NULL, msgDispatchWorker, NULL);
+    if (ret != 0) {
+        AML_LOGE("msgDispatchWorker pthread create failed......\n");
+        exit(-1);
+    }
+    ret = pthread_create(&clientSocketData.heartBeatDetect, NULL, heartBeatDetectWorker, NULL);
+    if (ret != 0) {
+        AML_LOGE("heartBeatDetectWorker pthread create failed......\n");
+        exit(-1);
+    }
+
+}
+
+void ClientExit(void)
+{
+    pthread_join(clientSocketData.dispatch, NULL);
+    pthread_join(clientSocketData.heartBeatDetect, NULL);
+}
diff --git a/aml_socketipc_v2/common/socket_client.h b/aml_socketipc_v2/common/socket_client.h
new file mode 100644
index 0000000..5452c9a
--- /dev/null
+++ b/aml_socketipc_v2/common/socket_client.h
@@ -0,0 +1,71 @@
+// Copyright (C) 2023 Amlogic, Inc. All rights reserved.
+//
+// All information contained herein is Amlogic confidential.
+//
+// This software is provided to you pursuant to Software License
+// Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be
+// used only in accordance with the terms of this agreement.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification is strictly prohibited without prior written permission
+// from Amlogic.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SOCKET_CLIENT_H_
+#define SOCKET_CLIENT_H_
+#include <pthread.h>
+#include "socket_util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Business general execution functions for messages from the server
+typedef void (*PerformActionForServerMessage)(char*);
+
+// Release of requested data
+typedef void (*FreeSpecificMessage)(void*);
+
+typedef struct {
+    int sockfd;
+    int beats;
+    char* connectIp;
+    int connectPort;
+    int registerBitmap; //register the required bitmap
+
+    pthread_mutex_t beatMutex;
+    pthread_mutex_t writeMsgMutex;
+    pthread_t dispatch;
+    pthread_t heartBeatDetect;
+
+    PerformActionForServerMessage clientHandler;
+} ClientSocketData;
+
+typedef struct {
+    int connectPort;
+    char* connectIp;
+    int registerBitmap;
+
+    PerformActionForServerMessage clientHandler;
+} ClientInputData;
+
+void ClientInit(ClientInputData* clientInputData);
+void ClientExit(void);
+int ClientWriteMsg2Server(MessageType msgType, void* msg, const int msgLength);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/aml_socketipc_v2/common/socket_server.c b/aml_socketipc_v2/common/socket_server.c
new file mode 100644
index 0000000..c7724a0
--- /dev/null
+++ b/aml_socketipc_v2/common/socket_server.c
@@ -0,0 +1,303 @@
+// Copyright (C) 2023 Amlogic, Inc. All rights reserved.
+//
+// All information contained herein is Amlogic confidential.
+//
+// This software is provided to you pursuant to Software License
+// Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be
+// used only in accordance with the terms of this agreement.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification is strictly prohibited without prior written permission
+// from Amlogic.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "util_list.h"
+#include <pthread.h>
+#include <pthread.h>
+#include <sys/epoll.h>
+#include "socket_server.h"
+
+#include "aml_log.h"
+
+ServerSocketData serverSocketData;
+
+void EnqueueServerMsg(void* msg, MessageType msgType, int msglength, int serverMsgType)
+{
+    if (UNDEFINED == msgType) {
+        AML_LOGW("Invalid message type......\n");
+        return;
+    }
+    MsgHeader header;
+    int totalSize = 0;
+
+    if (BUSINESS_DATA == msgType) {
+        header.type = BUSINESS_DATA;
+        header.dataLength = msglength;
+        totalSize = sizeof(header) + header.dataLength;
+    } else if (HEARTBEAT == msgType) {
+        header.type = HEARTBEAT;
+        header.dataLength = 0;
+        totalSize = sizeof(header);
+    }
+    char* buffer = (char*)malloc(totalSize);
+
+    memcpy(buffer, &header, sizeof(header));
+    if (BUSINESS_DATA == msgType) {
+        memcpy(buffer + sizeof(header), msg, header.dataLength);
+    }
+    pthread_mutex_lock(&serverSocketData.serverMsgsMutex);
+    push_back(serverSocketData.serverMsgsList, buffer, serverMsgType);
+    pthread_cond_signal(&serverSocketData.serverMsgsCond);
+    pthread_mutex_unlock(&serverSocketData.serverMsgsMutex);
+}
+
+/*
+    send a message or processing result to the client
+*/
+void* messageSenderWorker(void *arg)
+{
+    while (1) {
+        pthread_mutex_lock(&serverSocketData.serverMsgsMutex);
+        while (empty(serverSocketData.serverMsgsList)) {
+            pthread_cond_wait(&serverSocketData.serverMsgsCond, &serverSocketData.serverMsgsMutex);
+        }
+        if (!empty(serverSocketData.serverMsgsList)) {
+            // get business message type
+            int serverMsgType = -1;
+            void* pMsg = front(serverSocketData.serverMsgsList, &serverMsgType);
+
+            pthread_mutex_unlock(&serverSocketData.serverMsgsMutex);
+            // get header message information
+            MsgHeader extractedHeader;
+            memcpy(&extractedHeader, pMsg, sizeof(MsgHeader));
+            MessageType msgType = extractedHeader.type;
+
+            if (BUSINESS_DATA == msgType) {
+                int dataLenth = sizeof(MsgHeader) + extractedHeader.dataLength;
+                Node* it = serverSocketData.clientFdList->head;
+                while (it != NULL)
+                {
+                    int fd = *(int*)it->data;
+                    // If the fd device registers for this event send msg
+                    if ((it->nodeTypeData & (1 << serverMsgType)) != 0) {
+                        AML_LOGD("send business message to fd %d......\n", fd);
+                        if (write(fd, pMsg, dataLenth) != dataLenth)
+                            AML_LOGW("server write to client failed......\n");
+                    }
+                    it = it->next;
+                }
+            } else if (HEARTBEAT == msgType) {
+                int dataLenth = sizeof(MsgHeader);
+                Node* it = serverSocketData.clientFdList->head;
+
+                while (it != NULL)
+                {
+                    int fd = *(int*)it->data;
+                    if (write(fd, pMsg, dataLenth) != dataLenth)
+                        AML_LOGW("server write to client failed......\n");
+                    it = it->next;
+                }
+            }
+            free(pMsg);
+            pMsg = NULL;
+            pop_front(serverSocketData.serverMsgsList);
+        }
+    }
+}
+
+/*
+    handle heartbeat messages, send heartbeat messages to connected clients at regular intervals
+*/
+void* heartBeatSenderWorker(void *arg)
+{
+    while (1) {
+        EnqueueServerMsg(NULL, HEARTBEAT, 0, -1);
+        sleep(10);
+    }
+}
+
+/*
+    handle the registration message from the client
+*/
+void handleRegisterMessage(char* bitmapStr, int fd) {
+
+    int bitmapLen = sizeof(int) * 8;
+
+    int bitmap = atoi(bitmapStr);
+
+    AML_LOGD("receive client register message from fd %d, bitmap: %d\n", fd, bitmap);
+
+    // int ptr need malloc, remember to free
+    int* connfd_ptr = malloc(sizeof(int));
+    *connfd_ptr = fd;
+    push_back(serverSocketData.clientFdList, connfd_ptr, bitmap);
+    for (int j = 0; j < bitmapLen; j++) {
+        if ((bitmap & (1 << j )) != 0) {
+            AML_LOGD("server receive register %d , fd: %d \n", j, fd);
+        }
+    }
+}
+
+/*
+    listening to different events from client and handling them
+*/
+void* epollEventHandlerWorker(void *arg)
+{
+    int epollfd = epoll_create1(0);
+    if (epollfd == -1) {
+        AML_LOGE("epoll_create1 failed......\n");
+        exit(-1);
+    }
+
+    struct epoll_event ev;
+    ev.events = EPOLLIN;
+    ev.data.fd = serverSocketData.listen_fd;
+
+    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, serverSocketData.listen_fd, &ev) == -1) {
+        AML_LOGE("epoll_ctl failed......\n");
+        close(epollfd);
+        exit(-1);
+    }
+
+    #define MAX_EVENT 8
+    struct epoll_event events[MAX_EVENT];
+    while (1) {
+        int nfds = epoll_wait(epollfd, events, MAX_EVENT, -1);
+        if (nfds < 0) {
+            continue;
+        }
+
+        for (int i = 0; i < nfds; i++) {
+            if (events[i].data.fd == serverSocketData.listen_fd) {
+                int connfd = accept(serverSocketData.listen_fd, NULL, NULL);
+                if (connfd == -1 && errno != EINTR) {
+                    AML_LOGE("accept failed %d......\n", errno);
+                    close(epollfd);
+                    exit(-1);
+                }
+                if (connfd >= 0) {
+                    AML_LOGI("client connection arrvied, fd: %d......\n", connfd);
+                    ev.events = EPOLLIN;
+                    ev.data.fd = connfd;
+
+                    setNonblocking(connfd);
+                    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &ev) == -1) {
+                        AML_LOGE("epoll_ctl failed......\n");
+                        close(epollfd);
+                        exit(-1);
+                    }
+                }
+            } else {
+                // get message header
+                MsgHeader header;
+                int n = readn(events[i].data.fd, &header, sizeof(header));
+
+                if (0 == n) {
+                    AML_LOGI("client fd %d close connection......\n", events[i].data.fd);
+
+                    // delete special value node
+                    deleteIntNodeWithValue(serverSocketData.clientFdList, events[i].data.fd);
+
+                    if (epoll_ctl(epollfd, EPOLL_CTL_DEL, events[i].data.fd, NULL) == -1)
+                        AML_LOGE("epoll_ctl failed......\n");
+                    close(events[i].data.fd);
+                    continue;
+                }
+                MessageType type = header.type;
+                int dataLength = header.dataLength;
+
+                // get message body
+                char businessData[dataLength];
+
+                n = readn(events[i].data.fd, &businessData, sizeof(businessData));
+                if (0 == n) {
+                    AML_LOGI("client fd %d close connection......\n", events[i].data.fd);
+                    // delete special value node
+                    deleteIntNodeWithValue(serverSocketData.clientFdList, events[i].data.fd);
+
+                    if (epoll_ctl(epollfd, EPOLL_CTL_DEL, events[i].data.fd, NULL) == -1)
+                        AML_LOGE("epoll_ctl failed......\n");
+                    close(events[i].data.fd);
+                    continue;
+                }
+
+                if (type == REGISTER) {
+                    // Processing register message from the client
+                    handleRegisterMessage(businessData, events[i].data.fd);
+                } else if (type == BUSINESS_DATA) {
+                    // Processing business messages from the client, calling callback functions
+                    serverSocketData.serverHandler(businessData, events[i].data.fd);
+                }
+            }
+        }
+
+    }
+    close(epollfd);
+}
+
+void initServerData(ServerSocketData* serverSocketData, ServerInputData* serverInputData)
+{
+    if (!serverSocketData || !serverInputData) {
+        AML_LOGE("Null pointer passed to initServerData......\n");
+        return;
+    }
+
+    serverSocketData->serverHandler = serverInputData->serverHandler;
+
+    serverSocketData->clientFdList = createList();
+    serverSocketData->serverMsgsList= createList();
+    createListener(&serverSocketData->listen_fd, serverInputData->connectPort);
+}
+
+
+void ServerInit(ServerInputData* serverInputData)
+{
+    initServerData(&serverSocketData, serverInputData);
+
+    int ret = pthread_create(&serverSocketData.epollEventHandler, NULL, epollEventHandlerWorker, NULL);
+    if (ret != 0) {
+        AML_LOGE("epollEventHandlerWorker pthread create failed......\n");
+        exit(-1);
+    }
+    ret = pthread_create(&serverSocketData.messageSender, NULL, messageSenderWorker, NULL);
+    if (ret != 0) {
+        AML_LOGE("messageSenderWorker pthread create failed......\n");
+        exit(-1);
+    }
+    ret = pthread_create(&serverSocketData.heartBeatSender, NULL, heartBeatSenderWorker, NULL);
+    if (ret != 0) {
+        AML_LOGE("heartBeatSenderWorker pthread create failed......\n");
+        exit(-1);
+    }
+}
+
+void ServerExit(void)
+{
+    pthread_join(serverSocketData.epollEventHandler, NULL);
+    pthread_join(serverSocketData.messageSender, NULL);
+    pthread_join(serverSocketData.heartBeatSender, NULL);
+    // free and close
+    freeList(serverSocketData.clientFdList);
+    freeList(serverSocketData.serverMsgsList);
+    close(serverSocketData.listen_fd);
+}
\ No newline at end of file
diff --git a/aml_socketipc_v2/common/socket_server.h b/aml_socketipc_v2/common/socket_server.h
new file mode 100644
index 0000000..ba79d4d
--- /dev/null
+++ b/aml_socketipc_v2/common/socket_server.h
@@ -0,0 +1,67 @@
+// Copyright (C) 2023 Amlogic, Inc. All rights reserved.
+//
+// All information contained herein is Amlogic confidential.
+//
+// This software is provided to you pursuant to Software License
+// Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be
+// used only in accordance with the terms of this agreement.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification is strictly prohibited without prior written permission
+// from Amlogic.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SOCKET_SERVER_H_
+#define SOCKET_SERVER_H_
+#include <pthread.h>
+#include "util_list.h"
+#include "socket_util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Business general execution functions for messages from the client
+typedef void (*PerformActionForClientMessage)(char* buf, int fd);
+
+typedef struct {
+    int listen_fd;
+
+    List* clientFdList; // connected client fd
+    List* serverMsgsList; // message need to send
+
+    pthread_mutex_t serverMsgsMutex;
+    pthread_cond_t serverMsgsCond;
+    pthread_t epollEventHandler;
+    pthread_t messageSender;
+    pthread_t heartBeatSender;
+
+    PerformActionForClientMessage serverHandler;
+} ServerSocketData;
+
+typedef struct {
+    int connectPort;
+
+    PerformActionForClientMessage serverHandler;
+} ServerInputData;
+
+void ServerInit(ServerInputData* clientInputData);
+void ServerExit(void);
+void EnqueueServerMsg(void* msg, MessageType msgType, int msgLength, int serverMsgType);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/aml_socketipc_v2/common/socket_util.c b/aml_socketipc_v2/common/socket_util.c
new file mode 100644
index 0000000..87ab06a
--- /dev/null
+++ b/aml_socketipc_v2/common/socket_util.c
@@ -0,0 +1,185 @@
+// Copyright (C) 2023 Amlogic, Inc. All rights reserved.
+//
+// All information contained herein is Amlogic confidential.
+//
+// This software is provided to you pursuant to Software License
+// Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be
+// used only in accordance with the terms of this agreement.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification is strictly prohibited without prior written permission
+// from Amlogic.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+#include <errno.h>
+#include <stdbool.h>
+#include "socket_util.h"
+
+#include "aml_log.h"
+
+// Read "n" bytes from a descriptor
+ssize_t readn(int fd, void* vptr, ssize_t n)
+{
+    ssize_t  nleft;
+    ssize_t nread;
+    char* ptr;
+
+    ptr =(char*) vptr;
+    nleft = n;
+    while (nleft > 0) {
+        if ( (nread = read(fd, ptr, nleft)) < 0) {
+            if (errno == EINTR)
+                nread = 0;      /* and call read() again */
+            else
+                return -1;
+        } else if (nread == 0) {
+            break;              /* EOF */
+        }
+
+        nleft -= nread;
+        ptr   += nread;
+    }
+    return (n - nleft);      /* return >= 0 */
+}
+
+
+// Write "n" bytes to a descriptor
+ssize_t writen(int fd, const void* vptr, ssize_t n)
+{
+    ssize_t      nleft;
+    ssize_t     nwritten;
+    const char*  ptr;
+
+    ptr =(char*) vptr;
+    nleft = n;
+    while (nleft > 0) {
+        if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
+            if (nwritten < 0 && errno == EINTR)
+                nwritten = 0;       // and call write() again
+            else
+                return(-1);         // error
+        }
+
+        nleft -= nwritten;
+        ptr   += nwritten;
+    }
+    return n;
+}
+
+
+// for server
+void setNonblocking(int fd)
+{
+    int flags = fcntl(fd, F_GETFL, 0);
+    fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+}
+
+int createListener(int* global_listen_fd, int serverPort){
+    int flag = 1;
+    struct sockaddr_in serv_addr;
+    int listen_fd;
+    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
+    *global_listen_fd = listen_fd;
+    if (listen_fd < 0) {
+        AML_LOGE("create socket failed\n");
+        goto fail;
+    }
+    if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) < 0) {
+        AML_LOGE("setsockopt SO_REUSEADDR failed\n");
+        goto fail;
+    }
+    setNonblocking(listen_fd);
+    memset(&serv_addr, 0, sizeof(serv_addr));
+    serv_addr.sin_family = AF_INET;
+    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+    serv_addr.sin_port = htons(serverPort);
+
+    if (bind(listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
+        AML_LOGE("bind failed, %s\n", strerror(errno));
+        goto fail;
+    }
+    if (listen(listen_fd, 20) != 0) {
+        AML_LOGE("server listen failed\n");
+        goto fail;
+    }
+    AML_LOGI("server listen_fd: %d\n", listen_fd);
+    return 0;
+fail:
+    if (listen_fd > 0) {
+        close(listen_fd);
+        listen_fd = -1;
+    }
+    return -1;
+}
+
+// for client
+void initConnection(int* sockfd, const char *serverIP, int serverPort)
+{
+    struct sockaddr_in serv_addr;
+
+    *sockfd = socket(AF_INET, SOCK_STREAM, 0);
+    if (*sockfd < 0) {
+        AML_LOGE("create socket failed\n");
+        exit(-1);
+    }
+    memset(&serv_addr, 0, sizeof(serv_addr));
+    serv_addr.sin_family = AF_INET;
+    serv_addr.sin_port = htons(serverPort);
+    if (inet_pton(AF_INET, serverIP, &serv_addr.sin_addr) != 1) {
+        AML_LOGE("invalid address\n");
+        exit(-1);
+    }
+
+    int ret;
+    int seconds = 0;
+
+    while (true) {
+        ret = connect(*sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
+        if (ret == 0) {
+            break;
+        }
+        switch (errno) {
+        case EISCONN:
+            AML_LOGW("Socket is already connected. Closing and retrying.\n");
+            close(*sockfd);
+            *sockfd = socket(AF_INET, SOCK_STREAM, 0);  // creat new socket
+            if (*sockfd == -1) {
+                AML_LOGE("Error creating socket");
+                exit(EXIT_FAILURE);
+            }
+            break;
+        default:
+            AML_LOGW("try to connect to server, elapsed time: %d seconds, ret=%d, errno=%d \n", seconds + 1, ret, errno);
+        }
+
+        if (seconds > 1 && ((seconds + 1) % 120 == 0)) {
+            AML_LOGE("Error: Socket reconnection timed out.\n");
+            exit(EXIT_FAILURE);
+        }
+        sleep(1);
+        seconds++;
+    }
+
+    AML_LOGI("connect to server\n");
+}
\ No newline at end of file
diff --git a/aml_socketipc_v2/common/socket_util.h b/aml_socketipc_v2/common/socket_util.h
new file mode 100644
index 0000000..ec67f63
--- /dev/null
+++ b/aml_socketipc_v2/common/socket_util.h
@@ -0,0 +1,70 @@
+// Copyright (C) 2023 Amlogic, Inc. All rights reserved.
+//
+// All information contained herein is Amlogic confidential.
+//
+// This software is provided to you pursuant to Software License
+// Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be
+// used only in accordance with the terms of this agreement.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification is strictly prohibited without prior written permission
+// from Amlogic.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SOCKET_UTIL_H_
+#define SOCKET_UTIL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// 1、Public interface for socket communication
+#define LOCALHOST_IP "127.0.0.1"
+#define DEFAULT_IP "127.0.0.1"
+#define DEFAULT_PORT 6800
+
+// Basic socket operations
+// Read "n" bytes from a descriptor
+ssize_t readn(int fd, void* vptr, ssize_t n);
+// Write "n" bytes to a descriptor
+ssize_t writen(int fd, const void* vptr, ssize_t n);
+
+
+// 2、for server and client
+// for server
+void setNonblocking(int fd);
+int createListener(int* listen_fd, int serverPort);
+
+// for client
+void initConnection(int* sockfd, const char *serverIP, int serverPort); //init socket;return sockfd
+
+
+typedef enum {
+    UNDEFINED,
+    BUSINESS_DATA,
+    REGISTER,
+    HEARTBEAT
+} MessageType;
+
+typedef struct {
+    MessageType type;
+    int dataLength;
+} MsgHeader;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/aml_socketipc_v2/common/testList.c b/aml_socketipc_v2/common/testList.c
new file mode 100644
index 0000000..5523414
--- /dev/null
+++ b/aml_socketipc_v2/common/testList.c
@@ -0,0 +1,73 @@
+// Copyright (C) 2023 Amlogic, Inc. All rights reserved.
+//
+// All information contained herein is Amlogic confidential.
+//
+// This software is provided to you pursuant to Software License
+// Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be
+// used only in accordance with the terms of this agreement.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification is strictly prohibited without prior written permission
+// from Amlogic.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/* main.c */
+#include <stdio.h>
+#include <stdlib.h>
+#include "util_list.h"
+
+List* list;
+
+int main() {
+    // Take the int type as an example
+    list = createList();
+    NodeType nodetype = UNDEFINED_NODE;
+
+    int nodetypeData = 0;
+    int* num1 = malloc(sizeof(int));
+    int* num2 = malloc(sizeof(int));
+    int* num3 = malloc(sizeof(int));
+
+    *num1 = 1;
+    *num2 = 2;
+    *num3 = 3;
+
+    // push 1-2-3
+    push_back(list, num1, UNDEFINED_NODE, 0);
+    push_back(list, num2, UNDEFINED_NODE, 0);
+    push_back(list, num3, UNDEFINED_NODE, 0);
+
+    printf("%d\n", *(int*)front(list, &nodetype, &nodetypeData)); // Prints "1"
+    pop_front(list); // pop 1
+    pop_front(list); // pop 2
+    printf("%d\n", *(int*)front(list, &nodetype, &nodetypeData)); // Prints "3"
+
+    Node* it = list->head;
+    printf("%d\n", *(int*)it->data); // Prints "3"
+
+    // delete special node by int value
+    int value = 3;
+    deleteIntNodeWithValue(list, value);
+    printf("%d\n", empty(list)); // Prints "1"
+
+    // Don't forget to free the integers after using them
+    while (!empty(list)) {
+        free(front(list, &nodetype, &nodetypeData));
+        pop_front(list);
+    }
+
+    freeList(list);
+
+    return 0;
+}
\ No newline at end of file
diff --git a/aml_socketipc_v2/common/util_list.c b/aml_socketipc_v2/common/util_list.c
new file mode 100644
index 0000000..a63d0bd
--- /dev/null
+++ b/aml_socketipc_v2/common/util_list.c
@@ -0,0 +1,121 @@
+// Copyright (C) 2023 Amlogic, Inc. All rights reserved.
+//
+// All information contained herein is Amlogic confidential.
+//
+// This software is provided to you pursuant to Software License
+// Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be
+// used only in accordance with the terms of this agreement.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification is strictly prohibited without prior written permission
+// from Amlogic.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "util_list.h"
+
+#include "aml_log.h"
+
+List* createList() {
+    List* list = (List*) malloc(sizeof(List));
+    list->head = NULL;
+    list->tail = NULL;
+    return list;
+}
+
+void push_back(List* list, void* data, int nodetypeData) {
+    Node* node = (Node*) malloc(sizeof(Node));
+    node->data = data;
+    node->nodeTypeData = nodetypeData;
+    node->next = NULL;
+    if (list->head == NULL) {
+        node->prev = NULL;
+        list->head = node;
+        list->tail = node;
+    } else {
+        node->prev = list->tail;
+        list->tail->next = node;
+        list->tail = node;
+    }
+}
+
+void* front(List* list, int* nodetypeData) {
+    if (list->head != NULL) {
+        if (nodetypeData != NULL) {
+            *nodetypeData = list->head->nodeTypeData;
+        }
+
+        return list->head->data;
+    } else {
+        AML_LOGW("List is empty.\n");
+        return NULL;
+    }
+}
+
+void pop_front(List* list) {
+    if (list->head != NULL) {
+        Node* node = list->head;
+        list->head = list->head->next;
+        if (list->head != NULL) {
+            list->head->prev = NULL;
+        } else {
+            list->tail = NULL;
+        }
+        free(node);
+    } else {
+        AML_LOGW("List is empty.\n");
+    }
+}
+
+int empty(List* list) {
+    return list->head == NULL;
+}
+
+void freeList(List* list) {
+    Node* current = list->head;
+    Node* next;
+    while (current != NULL) {
+        next = current->next;
+        free(current);
+        current = next;
+    }
+    free(list);
+}
+
+void deleteIntNodeWithValue(List* list, int value){
+    Node* current = list->head;
+    while (current != NULL) {
+        if (*(int*)(current->data) == value) {
+            if (current->prev != NULL) {
+                current->prev->next = current->next;
+            } else {
+                list->head = current->next;
+            }
+
+            if (current->next != NULL) {
+                current->next->prev = current->prev;
+            } else {
+                list->tail = current->prev;
+            }
+
+            Node* toDelete = current;
+            current = current->next;
+            free((int*)(toDelete->data));
+            free(toDelete);
+        } else {
+            current = current->next;
+        }
+    }
+}
\ No newline at end of file
diff --git a/aml_socketipc_v2/common/util_list.h b/aml_socketipc_v2/common/util_list.h
new file mode 100644
index 0000000..b6eaf1c
--- /dev/null
+++ b/aml_socketipc_v2/common/util_list.h
@@ -0,0 +1,58 @@
+// Copyright (C) 2023 Amlogic, Inc. All rights reserved.
+//
+// All information contained herein is Amlogic confidential.
+//
+// This software is provided to you pursuant to Software License
+// Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be
+// used only in accordance with the terms of this agreement.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification is strictly prohibited without prior written permission
+// from Amlogic.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef UTIL_LIST_H
+#define UTIL_LIST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct Node {
+    // serverMsgsList : nodeTypeData represents the server message type
+    // clientFdList : nodeTypeData represents the event information registered for this fd (bitmap)
+    int nodeTypeData;
+    void* data;
+    struct Node* next;
+    struct Node* prev;
+} Node;
+
+typedef struct List {
+    Node* head;
+    Node* tail;
+} List;
+
+List* createList();
+void push_back(List* list, void* data, int nodetypeData);
+void* front(List* list, int* nodetypeData);
+void pop_front(List* list);
+int empty(List* list);
+void freeList(List* list);
+void deleteIntNodeWithValue(List* list, int value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/aml_socketipc_v2/server/Makefile b/aml_socketipc_v2/server/Makefile
new file mode 100644
index 0000000..cfa7ba5
--- /dev/null
+++ b/aml_socketipc_v2/server/Makefile
@@ -0,0 +1,28 @@
+# linux envs
+CC = gcc
+
+CFLAGS = -I. -I../common -pthread -g
+LDFLAGS = -L..
+# Assuming the .so file is in the .. directory. Adjust as necessary.
+# when run, need export LD_LIBRARY_PATH=..:$LD_LIBRARY_PATH
+# or install default lib
+
+SRCS = TestServer.c
+OBJS = $(SRCS:.c=.o)
+
+TARGET = server
+LIBS = -laml_socketipc_v2 -laml_log
+
+.PHONY: all clean
+
+all: $(TARGET)
+	rm -f $(OBJS)
+
+$(TARGET): $(OBJS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $(TARGET)
+
+.c.o:
+	$(CC) $(CFLAGS) -c $< -o $@
+
+clean:
+	rm -f $(OBJS) $(TARGET)
diff --git a/aml_socketipc_v2/server/TestServer.c b/aml_socketipc_v2/server/TestServer.c
new file mode 100644
index 0000000..5292f0b
--- /dev/null
+++ b/aml_socketipc_v2/server/TestServer.c
@@ -0,0 +1,229 @@
+// Copyright (C) 2023 Amlogic, Inc. All rights reserved.
+//
+// All information contained herein is Amlogic confidential.
+//
+// This software is provided to you pursuant to Software License
+// Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be
+// used only in accordance with the terms of this agreement.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification is strictly prohibited without prior written permission
+// from Amlogic.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include "socket_server.h"
+
+extern ServerSocketData serverSocketData;
+
+//This is a demo about how to use server api
+/*
+    **************************************************************
+    Defining business data
+    **************************************************************
+*/
+
+enum ServerMsgType {
+    SERVERMSGTYPE1,
+    SERVERMSGTYPE2,
+    SERVERMSGTYPE3,
+    //...... other type message
+
+    MAXServerMsg
+};
+
+enum ServerMsgType2 {
+    SERVERMSGTYPE2VALUE1,
+    SERVERMSGTYPE2VALUE2
+};
+
+typedef struct ServerMsg {
+    enum ServerMsgType type;
+    union {
+        int serverMsgType1Value;
+        enum ServerMsgType2 serverMsgType2Value;
+        float serverMsgType3Value;
+        //...... other message's arguments
+    } u;
+} ServerMsgT;
+
+enum ClientMsgType {
+    CLIENTMSGTYPE1,
+    CLIENTMSGTYPE2,
+    //...... other type message
+
+    MAXClientMsg
+};
+
+enum ClientMsgType2 {
+    CLIENTMSGTYPE2VALUE1,
+    CLIENTMSGTYPE2VALUE2
+};
+
+typedef struct ClientMsg {
+    enum ClientMsgType type;
+    union {
+        int clientMsgType1Value;
+        enum ClientMsgType2 clientMsgType2Value;
+        //...... other message's arguments
+    } u;
+} ClientMsgT;
+/*
+    **************************************************************
+    Defining business data finish
+    **************************************************************
+*/
+
+typedef int (*ServerMsgHandler)(ServerMsgT*);
+
+// 1.callback function
+void handleClientMsgAction(char* buf, int fd);
+
+// 2.business action functions for sending to client
+void sendServerMsgType1(int msgTypeValue);
+void sendServerMsgType2(enum ServerMsgType2 msgTypeValue);
+void sendServerMsgType3(float msgTypeValue);
+
+// 3.business action functions for receiving client message
+void clientMsgType1ActHandle(ClientMsgT* msg);
+void clientMsgType2ActHandle(ClientMsgT* msg);
+
+// 4.initiclientMsgType1ActHandlealization related parameters
+void initializeServerInputData(ServerInputData* serverInputData, int port);
+
+/*
+    *******************************************************
+    Specific function definitions
+    *******************************************************
+*/
+
+void handleClientMsgAction(char* buf, int fd)
+{
+    ClientMsgT* msg = (ClientMsgT*) buf;
+
+    if (msg->type == CLIENTMSGTYPE1) { //handle message from client
+        printf("receive client clientMsgType1 message from fd %d, value is : %d \n", fd, msg->u.clientMsgType1Value);
+        clientMsgType1ActHandle(msg);
+    } else if (msg->type == CLIENTMSGTYPE2) { //handle message from client
+        printf("receive client clientMsgType2 message from fd %d, value is : %d \n", fd, msg->u.clientMsgType2Value);
+        clientMsgType2ActHandle(msg);
+    }
+}
+
+void clientMsgType1ActHandle(ClientMsgT* msg)
+{
+    printf("receive client MsgType1, value is %d \n", msg->u.clientMsgType1Value);
+}
+void clientMsgType2ActHandle(ClientMsgT* msg)
+{
+    printf("receive client MsgType2, value is %d \n", msg->u.clientMsgType2Value);
+}
+
+void sendServerMsgType1(int msgTypeValue)
+{
+    ServerMsgT msg;
+    msg.type = SERVERMSGTYPE1;
+    msg.u.serverMsgType1Value = msgTypeValue;
+
+    printf("send server MsgType1 to client, value is %d \n", msgTypeValue);
+
+    EnqueueServerMsg(&msg, BUSINESS_DATA, sizeof(msg), msg.type);
+}
+
+void sendServerMsgType2(enum ServerMsgType2 msgTypeValue)
+{
+    ServerMsgT msg;
+    msg.type = SERVERMSGTYPE2;
+    msg.u.serverMsgType2Value = msgTypeValue;
+
+    printf("send server MsgType2 to client, value is %d \n", msgTypeValue);
+
+    EnqueueServerMsg(&msg, BUSINESS_DATA, sizeof(msg), msg.type);
+}
+
+void sendServerMsgType3(float msgTypeValue)
+{
+    ServerMsgT msg;
+    msg.type = SERVERMSGTYPE3;
+    msg.u.serverMsgType3Value = msgTypeValue;
+
+    printf("send server MsgType3 to client, value is %f \n", msgTypeValue);
+
+    EnqueueServerMsg(&msg, BUSINESS_DATA, sizeof(msg), msg.type);
+}
+
+void initializeServerInputData(ServerInputData* serverInputData, int port)
+{
+
+    serverInputData->connectPort = port;
+
+    serverInputData->serverHandler = handleClientMsgAction;
+}
+
+int main(int argc, char *argv[])
+{
+    setvbuf(stdout, NULL, _IONBF, 0);
+
+    ServerInputData serverInputData;
+    initializeServerInputData(&serverInputData, DEFAULT_PORT);
+    ServerInit(&serverInputData);
+
+    printf("----------------finsh initialize------------------\n");
+
+    int msgType = -1;
+    int value = -1;
+    while (1) {
+        /*
+        Server sends command simulation
+        serverMsgType1 cmd "1":
+        enter int value:
+
+        serverMsgType2 cmd "2":
+        enter int value:
+
+        serverMsgType3 cmd "3":
+        enter int value:
+        */
+        printf("please enter the msgtype 1-3: ");
+        printf("\n");
+        scanf("%d", &msgType);
+        printf("\n");
+        if (1 == msgType) {
+
+            printf("please input msgtype1 value: ");
+            scanf("%d", &value);
+            printf("\n");
+            sendServerMsgType1(value);
+
+        } else if (2 == msgType) {
+            printf("please input msgtype2 value 0-1: ");
+            scanf("%d", &value);
+            printf("\n");
+            sendServerMsgType2(value);
+        } else if (3 == msgType) {
+            float value;
+            printf("please input msgtype3 value: ");
+            scanf("%f", &value);
+            printf("\n");
+            sendServerMsgType3(value);
+        }
+        msgType = -1;
+        value = -1;
+        printf("\n");
+        printf("\n");
+    }
+    ServerExit();
+}
\ No newline at end of file
diff --git a/aml_socketipc_v2/timing_diagram.md b/aml_socketipc_v2/timing_diagram.md
new file mode 100644
index 0000000..2adbbae
--- /dev/null
+++ b/aml_socketipc_v2/timing_diagram.md
@@ -0,0 +1,40 @@
+```mermaid
+%%{init: {'theme':'default', 'themeVariables': {'fontSize': '30px'}}}%%
+sequenceDiagram
+%%   title Client-Server Communication Interface Timing Diagram
+  
+  Note right of ClientMain: Client Side Components
+  participant ClientMain as Client Main Thread
+  participant MsgWorker as Client msgDispatchWorker Thread
+  participant HeartbeatWorker as Client Heartbeat Thread
+  
+  Note left of ServerMain: Server Side Components
+  participant ServerMain as Server Main Thread
+  participant HeartbeatSender as Server heartBeatSenderWorker Thread
+  participant EpollHandler as Server epollEventHandlerWorker Thread
+  participant MsgSender as Server Message Sender Thread
+
+  ClientMain-->>EpollHandler: Send connection request to server
+  EpollHandler->>EpollHandler: Accept new client connection and establish it
+
+  loop Every 10s
+    HeartbeatSender->>MsgSender: Send Heartbeat message by EnqueueServerMsg
+  end
+  
+  loop Listen for heartbeat data
+    HeartbeatWorker->>HeartbeatWorker: Check for Heartbeat
+    alt No Heartbeat in 30s
+      HeartbeatWorker-->>HeartbeatWorker: Reconnect and register
+    end
+  end
+  
+  loop Message send and receive
+    ClientMain-->>EpollHandler: send client message to server
+    EpollHandler->>EpollHandler: Listen for client messages (includes registration and business messages)
+    EpollHandler->>ServerMain: Call serverHandler for each received message
+    ServerMain->>MsgSender: Send business message by EnqueueServerMsg
+    MsgSender-->>MsgWorker: Send server message to client
+    MsgWorker->>MsgWorker: Receive message from server
+    MsgWorker->>ClientMain: Call clientHandler
+  end
+```
\ No newline at end of file