webrtc_test: Add test case to send/receive a file via data channel 17/247817/3
authorSangchul Lee <sc11.lee@samsung.com>
Tue, 17 Nov 2020 07:08:38 +0000 (16:08 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Tue, 17 Nov 2020 10:44:23 +0000 (19:44 +0900)
[Version] 0.1.55
[Issue Type] Test application

Change-Id: Ie38f3d76a1c6b47f14a1ee7e3b1be74bb729f81a
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
packaging/capi-media-webrtc.spec
test/webrtc_test.c

index f6a9b293a4ca289f2c42760b8d7f77e3a5c559a1..df2c2fc30fb975bead860afbadee0530fbfa80b3 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-webrtc
 Summary:    A WebRTC library in Tizen Native API
-Version:    0.1.54
+Version:    0.1.55
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index 7f2cffce5252cd67df55ea24b49d4b0f5c6453ea..01224b7fe823aeb74fb7f6cabf89ef9c3bf86e7a 100644 (file)
@@ -20,6 +20,9 @@
 #include <glib.h>
 #include <libsoup/soup.h>
 #include <json-glib/json-glib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 
 #ifdef PACKAGE
 #undef PACKAGE
@@ -41,7 +44,8 @@ enum {
        CURRENT_STATUS_GET_TRANSCEIVER_DIRECTION,
        CURRENT_STATUS_SET_TRANSCEIVER_DIRECTION,
        CURRENT_STATUS_DATA_CHANNEL_SEND_STRING,
-       CURRENT_STATUS_DATA_CHANNEL_SEND_BYTES,
+       CURRENT_STATUS_DATA_CHANNEL_SEND_STRING_AS_BYTES,
+       CURRENT_STATUS_DATA_CHANNEL_SEND_FILE,
        CURRENT_STATUS_SET_STUN_SERVER,
        CURRENT_STATUS_SET_LOCAL_DESCRIPTION,
        CURRENT_STATUS_SET_REMOTE_DESCRIPTION,
@@ -110,6 +114,11 @@ static int g_server_status = SERVER_STATUS_DISCONNECTED;
 static int g_menu_state = CURRENT_STATUS_MAINMENU;
 static int g_cnt;
 
+/* receive data & dump file */
+static gchar *g_expected_name;
+static int g_expected_size;
+static char* g_receive_buffer;
+
 static void win_del(void *data, Evas_Object *obj, void *event)
 {
        elm_exit();
@@ -401,7 +410,7 @@ static void _webrtc_data_channel_send_string(const char *string)
        }
 }
 
-static void _webrtc_data_channel_send_bytes(const char *string)
+static void _webrtc_data_channel_send_string_as_bytes(const char *string)
 {
        int ret = WEBRTC_ERROR_NONE;
        int i;
@@ -410,7 +419,7 @@ static void _webrtc_data_channel_send_bytes(const char *string)
                if (g_channels[i] == NULL)
                        continue;
                g_print("data_channel[%p], index[%d]: ", g_channels[i], i);
-               ret = webrtc_data_channel_send_bytes(g_channels[i], (void*)string, strlen(string));
+               ret = webrtc_data_channel_send_bytes(g_channels[i], string, strlen(string));
                if (ret != WEBRTC_ERROR_NONE)
                        g_print("failed to webrtc_data_channel_send_bytes(), string[%s]\n", string);
                else
@@ -418,6 +427,71 @@ static void _webrtc_data_channel_send_bytes(const char *string)
        }
 }
 
+static void _webrtc_data_channel_send_file(const char *file_path)
+{
+       #define BUFFER_SIZE 16 * 1024 /* 16 kbytes */
+       int ret = WEBRTC_ERROR_NONE;
+       int i;
+       struct stat st;
+       gchar *expected_name;
+       gchar *expected_size;
+       ssize_t read_size;
+       ssize_t sum_size;
+       char buffer[BUFFER_SIZE] = {0, };
+       int fd;
+
+       for (i = 0; i < MAX_CHANNEL_LEN; i++) {
+               if (g_channels[i] == NULL)
+                       continue;
+               g_print("data_channel[%p], index[%d]: ", g_channels[i], i);
+
+               fd = open(file_path, O_RDONLY);
+               if (fd == -1) {
+                       g_print("failed to open file[%s]", file_path);
+                       return;
+               }
+               if (fstat(fd, &st) == -1) {
+                       g_print("failed to fstat()");
+                       close(fd);
+                       return;
+               }
+
+               /* NOTE that logic regarding sending file size and name before sending data may differ from application implementations.
+                * Here we use two magic string - 'expected name:' and 'expected size:' */
+               expected_size = g_strdup_printf("expected size:%llu", st.st_size);
+               expected_name = g_strdup_printf("expected name:%s", basename((char *)file_path));
+
+               ret = webrtc_data_channel_send_string(g_channels[i], expected_size);
+               if (ret != WEBRTC_ERROR_NONE)
+                       g_print("failed to webrtc_data_channel_send_string(), string[%s]\n", expected_size);
+               else
+                       g_print("webrtc_data_channel_send_string() success, string[%s]\n", expected_size);
+
+               ret = webrtc_data_channel_send_string(g_channels[i], expected_name);
+               if (ret != WEBRTC_ERROR_NONE)
+                       g_print("failed to webrtc_data_channel_send_string(), string[%s]\n", expected_name);
+               else
+                       g_print("webrtc_data_channel_send_string() success, string[%s]\n", expected_name);
+
+               g_free(expected_size);
+               g_free(expected_name);
+
+               sum_size = 0;
+               while((read_size = read(fd, buffer, BUFFER_SIZE)) > 0) {
+                       sum_size += read_size;
+                       g_print("[%zd / %llu]bytes is read", sum_size, st.st_size);
+
+                       ret = webrtc_data_channel_send_bytes(g_channels[i], buffer, (unsigned int)read_size);
+                       if (ret != WEBRTC_ERROR_NONE)
+                               g_print("failed to webrtc_data_channel_send_bytes(), file_path[%s], size[%zd]\n", file_path, read_size);
+                       else
+                               g_print("webrtc_data_channel_send_bytes() success, file_path[%s], size[%zd]\n", file_path, read_size);
+               }
+
+               close(fd);
+       }
+}
+
 static void _webrtc_set_stun_server(char *uri)
 {
        int ret = 0;
@@ -441,21 +515,99 @@ static void __data_channel_open_cb(webrtc_data_channel_h channel, void *user_dat
        g_print("__data_channel_open_cb() is called, channel[%p]\n", channel);
 }
 
+static void __file_dump(const gchar *file_name, void *src_buffer, int size)
+{
+       int fd;
+       gchar *full_path;
+
+       if (file_name == NULL) {
+               g_print("file_name is NULL\n");
+               return;
+       }
+       if (src_buffer == NULL) {
+               g_print("src_buffer is NULL\n");
+               return;
+       }
+
+       full_path = g_strdup_printf("/tmp/%s", file_name);
+
+       fd = open(full_path, O_WRONLY | O_CREAT, 0644);
+       if (fd == -1) {
+               g_print("failed to open file[%s]\n", full_path);
+               goto end;
+       }
+
+       if (write(fd, src_buffer, size) == -1)
+               g_print("failed to write file[%s]\n", full_path);
+
+       g_print("[%s, %d bytes] is ready\n", full_path, size);
+
+end:
+       g_free(full_path);
+       close(fd);
+}
+
 static void __data_channel_message_cb(webrtc_data_channel_h channel, webrtc_data_channel_type_e type, void *message, void *user_data)
 {
        g_print("__data_channel_message_cb() is called, channel[%p], type[%d], ", channel, type);
+
        if (type == WEBRTC_DATA_CHANNEL_TYPE_STRING) {
+               gchar **str_arr = NULL;
+
                g_print("string message[%s]\n", (char *)message);
+
+               if (g_str_has_prefix((const gchar *)message, "expected name:")) {
+                       str_arr = g_strsplit((const gchar *)message, ":", 2);
+                       g_free(g_expected_name);
+                       g_expected_name = g_strdup(str_arr[1]);
+
+               } else if (g_str_has_prefix((const gchar *)message, "expected size:")) {
+                       str_arr = g_strsplit((const gchar *)message, ":", 2);
+                       g_expected_size = atoi(str_arr[1]);
+
+                       if (g_receive_buffer)
+                               free(g_receive_buffer);
+                       g_receive_buffer = (char *)calloc(g_expected_size, sizeof(char));
+               }
+
+               if (str_arr)
+                       g_strfreev(str_arr);
+
        } else if (type == WEBRTC_DATA_CHANNEL_TYPE_BYTES) {
                webrtc_bytes_data_h *data = message;
                const char *data_p;
                unsigned int size;
                int i = 0;
+
                webrtc_get_data(data, &data_p, &size);
                g_print("bytes message[%p, size:%u]\n", data_p, size);
-               for (i = 0; i < size; i++)
-                       g_print("%c", data_p[i]);
-               g_print("\n");
+
+               if (g_expected_size > 0 && g_expected_name) {
+                       static int sum_size = 0;
+
+                       g_print("downloading [%s], size[%d / %d]\n", g_expected_name, sum_size, g_expected_size);
+
+                       memcpy(&g_receive_buffer[sum_size], ((uint8_t*)data_p), size);
+
+                       sum_size += size;
+                       if (sum_size >= g_expected_size) {
+                               __file_dump(g_expected_name, g_receive_buffer, sum_size);
+
+                               sum_size = 0;
+                               g_expected_size = 0;
+                               g_free(g_expected_name);
+                               g_expected_name = NULL;
+                               if (g_receive_buffer) {
+                                       free(g_receive_buffer);
+                                       g_receive_buffer = NULL;
+                               }
+                       }
+
+               } else {
+                       for (i = 0; i < size; i++)
+                               g_print("%c", data_p[i]);
+                       g_print("\n");
+               }
        }
 }
 
@@ -1057,7 +1209,10 @@ void _interpret_main_menu(char *cmd)
                        g_menu_state = CURRENT_STATUS_DATA_CHANNEL_SEND_STRING;
 
                } else if (strncmp(cmd, "zb", 2) == 0) {
-                       g_menu_state = CURRENT_STATUS_DATA_CHANNEL_SEND_BYTES;
+                       g_menu_state = CURRENT_STATUS_DATA_CHANNEL_SEND_STRING_AS_BYTES;
+
+               } else if (strncmp(cmd, "zf", 2) == 0) {
+                       g_menu_state = CURRENT_STATUS_DATA_CHANNEL_SEND_FILE;
 
                } else if (strncmp(cmd, "se", 2) == 0) {
                        _webrtc_set_error_cb();
@@ -1186,8 +1341,9 @@ void display_sub_basic()
        g_print("td. Set transceiver direction\n");
        g_print("cd. Create data channel\t");
        g_print("dd. Destroy data channel\n");
-       g_print("zs. Send string via data channel\t");
-       g_print("zb. Send bytes data via data channel\n");
+       g_print("zs. Send string via data channel\n");
+       g_print("zb. Send string as bytes data via data channel\t");
+       g_print("zf. Send file via data channel\n");
        g_print("------------------------------------- Callbacks -----------------------------------------\n");
        g_print("se. Set error callback\t");
        g_print("ue. Unset error callback\n");
@@ -1247,9 +1403,12 @@ static void displaymenu()
        } else if (g_menu_state == CURRENT_STATUS_DATA_CHANNEL_SEND_STRING) {
                g_print("*** input string to send.\n");
 
-       } else if (g_menu_state == CURRENT_STATUS_DATA_CHANNEL_SEND_BYTES) {
+       } else if (g_menu_state == CURRENT_STATUS_DATA_CHANNEL_SEND_STRING_AS_BYTES) {
                g_print("*** input string to send.(it will be converted to bytes data)\n");
 
+       } else if (g_menu_state == CURRENT_STATUS_DATA_CHANNEL_SEND_FILE) {
+               g_print("*** input file path to send.\n");
+
        } else if (g_menu_state == CURRENT_STATUS_SET_STUN_SERVER) {
                g_print("*** input STUN server address.\n");
 
@@ -1363,8 +1522,13 @@ static void interpret(char *cmd)
                reset_menu_state();
                break;
        }
-       case CURRENT_STATUS_DATA_CHANNEL_SEND_BYTES: {
-               _webrtc_data_channel_send_bytes(cmd);
+       case CURRENT_STATUS_DATA_CHANNEL_SEND_STRING_AS_BYTES: {
+               _webrtc_data_channel_send_string_as_bytes(cmd);
+               reset_menu_state();
+               break;
+       }
+       case CURRENT_STATUS_DATA_CHANNEL_SEND_FILE: {
+               _webrtc_data_channel_send_file(cmd);
                reset_menu_state();
                break;
        }