#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
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,
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();
}
}
-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;
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
}
}
+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;
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");
+ }
}
}
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();
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");
} 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");
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;
}