-
-
Save anonymous/ae8aae0c5901a68bb7f9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <winsock2.h>//part of Nice | |
#include <Windows.h> | |
#undef GetNextSibling | |
#undef GetFirstChild | |
///parts of nice | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <ctype.h> | |
#include <agent.h> | |
///parts of nice | |
#include "include/cef_app.h" | |
#include "include/cef_v8.h" | |
#include "Brest.h" | |
#include "bareboneshandler.h" | |
#include "MyV8Stuff.h" | |
// Define this, define that, define everything! | |
//#define TEST_SINGLE_THREADED_MESSAGE_LOOP | |
#define JS_BUTTON 1001 | |
CefRefPtr<MainBindings> rnd_handler; | |
static GMainLoop *gloop; | |
static gchar *stun_addr = NULL; | |
static guint stun_port; | |
static gboolean controlling; | |
static gboolean exit_thread, candidate_gathering_done, negotiation_done; | |
NiceAgent *agent; | |
static guint stream_id; | |
#if (GLIB_MAJOR_VERSION <= 2) && (GLIB_MINOR_VERSION < 32) //Glib version check | |
static GCond *gather_cond, *negotiate_cond; | |
static GMutex *gather_mutex, *negotiate_mutex; | |
#else | |
static GCond gather_cond, negotiate_cond; | |
static GMutex gather_mutex, negotiate_mutex; | |
#endif | |
static const gchar *state_name[] = {"disconnected", "gathering", "connecting", | |
"connected", "ready", "failed"}; | |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nShowCmd) | |
{ | |
WNDCLASSEX wClass; | |
CefSettings settings; | |
cf_handler = new BareBonesHandler(); | |
rnd_handler = new MainBindings(); | |
GThread *gexamplethread; | |
CefMainArgs main_args(hInst); | |
#ifdef G_OS_WIN32 | |
WSADATA w; | |
WSAStartup(0x0202, &w); | |
#endif | |
ZeroMemory(&wClass,sizeof(WNDCLASSEX)); | |
wClass.cbClsExtra=NULL; | |
wClass.cbSize=sizeof(WNDCLASSEX); | |
wClass.cbWndExtra=NULL; | |
wClass.hbrBackground=(HBRUSH)COLOR_WINDOW; | |
wClass.hCursor=LoadCursor(NULL,IDC_ARROW); | |
wClass.hIcon=NULL; | |
wClass.hIconSm=NULL; | |
wClass.hInstance=hInst; | |
wClass.lpfnWndProc=(WNDPROC)WinProc; | |
wClass.lpszClassName=L"Window Class"; | |
wClass.lpszMenuName=NULL; | |
wClass.style=CS_HREDRAW|CS_VREDRAW; | |
if(!RegisterClassEx(&wClass)) | |
{ | |
int nResult=GetLastError(); | |
MessageBox(NULL, | |
L"Window class creation failed", | |
L"Window Class Failed", | |
MB_ICONERROR); | |
} | |
int exitCode = CefExecuteProcess(main_args, rnd_handler.get()); | |
if (exitCode >= 0) { | |
return exitCode; | |
} | |
CefInitialize(main_args, settings, rnd_handler.get()); | |
HWND hWnd=CreateWindowEx(NULL, | |
L"Window Class", | |
L"Testing Viewium", | |
WS_OVERLAPPEDWINDOW, | |
200, | |
200, | |
1280, | |
768, | |
NULL, | |
NULL, | |
hInst, | |
NULL); | |
if(!hWnd) | |
{ | |
int nResult=GetLastError(); | |
MessageBox(NULL, | |
L"Window creation failed", | |
L"Window Creation Failed", | |
MB_ICONERROR); | |
} | |
ShowWindow(hWnd,nShowCmd); | |
g_type_init(); | |
exit_thread = FALSE; | |
#if (GLIB_MAJOR_VERSION <= 2) && (GLIB_MINOR_VERSION < 32) | |
gexamplethread = g_thread_create(&example_thread, NULL, TRUE, NULL); | |
#else | |
gexamplethread = g_thread_new("example thread", &example_thread, NULL); | |
#endif | |
// Run the mainloop. Everything else will happen asynchronously | |
CefRunMessageLoop(); | |
//Loop integration Test | |
/*while(GetMessage(&Msg, NULL, 0, 0) > 0) | |
{ | |
TranslateMessage(&Msg); | |
DispatchMessage(&Msg); | |
CefDoMessageLoopWork(); | |
g_main_context_iteration(g_main_loop_get_context (gloop), FALSE); | |
} | |
return Msg.wParam;*/ | |
/// | |
g_thread_join (gexamplethread); | |
g_main_loop_unref(gloop); | |
exit_thread = TRUE; | |
#ifdef G_OS_WIN32 | |
WSACleanup(); | |
#endif | |
CefShutdown(); | |
return EXIT_SUCCESS; | |
} | |
LRESULT CALLBACK WinProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) | |
{ | |
static HWND hJSButton; | |
LONG btny; | |
switch(msg) | |
{ | |
case WM_DESTROY: | |
{ | |
cf_handler->m_Browser = NULL; | |
CefQuitMessageLoop(); | |
PostQuitMessage(0); | |
return 0; | |
} | |
break; | |
case WM_CREATE: | |
{ | |
RECT rect; | |
GetClientRect(hWnd, &rect); | |
CefWindowInfo info; | |
rect.bottom = rect.bottom - 100; | |
info.SetAsChild(hWnd, rect); | |
CefBrowserSettings settings; | |
cf_handler->m_Browser = CefBrowserHost::CreateBrowserSync(info, cf_handler.get(), | |
"http://localhost:4242/chattest", settings); | |
/*cf_handler->m_Browser = CefBrowserHost::CreateBrowserSync(info, cf_handler.get(), | |
"http://www.youtube.com/watch?v=MyUC_28HIvA", settings);*/ | |
btny = rect.bottom + 25; | |
hJSButton = CreateWindow( L"button", L"JSButton", | |
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, | |
50, btny, | |
100, 50, | |
hWnd, (HMENU) JS_BUTTON, | |
NULL, NULL ); | |
} | |
break; | |
case WM_COMMAND: | |
{ | |
switch(wParam) | |
{ | |
case JS_BUTTON: | |
//jprint("JS Changing that string!"); | |
//binding = "olaola"; | |
//jprint(binding.c_str()); | |
//SendtoRender("TextData", "And now its changed"); | |
//jprint(binding); | |
return 0; | |
} | |
break; | |
} | |
break; | |
} | |
return DefWindowProc(hWnd,msg,wParam,lParam); | |
} | |
static void *example_thread(void *data) | |
{ | |
NiceAgent *agent; | |
guint stream_id; | |
//Create gloop | |
#if (GLIB_MAJOR_VERSION <= 2) && (GLIB_MINOR_VERSION < 32) | |
gather_cond = g_cond_new(); | |
negotiate_cond = g_cond_new(); | |
gather_mutex = g_mutex_new(); | |
negotiate_mutex = g_mutex_new(); | |
#endif | |
gloop = g_main_loop_new(NULL, FALSE); | |
// Create the nice agent | |
agent = nice_agent_new(g_main_loop_get_context (gloop), | |
NICE_COMPATIBILITY_RFC5245); | |
if (agent == NULL) | |
g_error("Failed to create agent"); | |
// | |
// Set the STUN settings and controlling mode | |
stun_addr = "77.72.174.163"; | |
stun_port = 3478; | |
controlling = 1; | |
g_debug("Using stun server '[%s]:%u'\n", stun_addr, stun_port); | |
g_object_set(G_OBJECT(agent), "stun-server", stun_addr, NULL); | |
g_object_set(G_OBJECT(agent), "stun-server-port", stun_port, NULL); | |
g_object_set(G_OBJECT(agent), "controlling-mode", controlling, NULL); | |
// Connect to the signals | |
g_signal_connect(G_OBJECT(agent), "candidate-gathering-done", | |
G_CALLBACK(cb_candidate_gathering_done), NULL); | |
g_signal_connect(G_OBJECT(agent), "new-selected-pair", | |
G_CALLBACK(cb_new_selected_pair), NULL); | |
g_signal_connect(G_OBJECT(agent), "component-state-changed", | |
G_CALLBACK(cb_component_state_changed), NULL); | |
// Create a new stream with one component | |
stream_id = nice_agent_add_stream(agent, 1); | |
if (stream_id == 0) | |
g_error("Failed to add stream"); | |
nice_agent_set_stream_name (agent, stream_id, "text"); | |
// Attach to the component to receive the data | |
// Without this call, candidates cannot be gathered | |
nice_agent_attach_recv(agent, stream_id, 1, | |
g_main_loop_get_context (gloop), cb_nice_recv, NULL); | |
// Start gathering local candidates | |
if (!nice_agent_gather_candidates(agent, stream_id)) | |
jprint("Failed to start candidate gathering"); | |
jprint("waiting for candidate-gathering-done signal..."); | |
if (exit_thread) | |
goto end; | |
g_main_loop_run (gloop); | |
end: | |
g_object_unref(agent); | |
g_main_loop_quit (gloop); | |
exit_thread = TRUE; | |
return NULL; | |
} | |
void jprint(const gchar *data) { | |
CefRefPtr<CefBrowser> browser; | |
if (cf_handler.get()) | |
browser = cf_handler->GetBrowser(); | |
if (browser.get()) { | |
CefRefPtr<CefFrame> frame = browser->GetMainFrame(); | |
gchar *jprint = g_strdup_printf("%s%s%s", "print('", data, "');"); | |
frame->ExecuteJavaScript(jprint, | |
frame->GetURL(), 0); | |
} | |
} | |
void SendtoRender(gchar *name, gchar *insides) | |
{ | |
CefRefPtr<CefBrowser> browser; | |
if (cf_handler.get()) | |
browser = cf_handler->GetBrowser(); | |
// Create the message object. | |
CefRefPtr<CefProcessMessage> msg= CefProcessMessage::Create(name); | |
// Retrieve the argument list object. | |
CefRefPtr<CefListValue> args = msg->GetArgumentList(); | |
// Populate the argument values. | |
args->SetString(0, insides); | |
// Send the process message to the render process. | |
// Use PID_BROWSER instead when sending a message to the browser process. | |
browser->SendProcessMessage(PID_RENDERER, msg); | |
} | |
void SendtoBoolRender(gchar *name, gboolean insides) | |
{ | |
CefRefPtr<CefBrowser> browser; | |
if (cf_handler.get()) | |
browser = cf_handler->GetBrowser(); | |
// Create the message object. | |
CefRefPtr<CefProcessMessage> msg= CefProcessMessage::Create(name); | |
// Retrieve the argument list object. | |
CefRefPtr<CefListValue> args = msg->GetArgumentList(); | |
// Populate the argument values. | |
args->SetBool(0, insides); | |
// Send the process message to the render process. | |
// Use PID_BROWSER instead when sending a message to the browser process. | |
browser->SendProcessMessage(PID_RENDERER, msg); | |
} | |
void SendtoBrowser(gchar *name, std::string insides) | |
{ | |
//CefRefPtr<CefBrowser> browser; | |
// if (cf_handler.get()) | |
CefRefPtr<CefBrowser> browser = rnd_handler->browserglobal; | |
// Create the message object. | |
CefRefPtr<CefProcessMessage> msg= CefProcessMessage::Create(name); | |
// Retrieve the argument list object. | |
CefRefPtr<CefListValue> args = msg->GetArgumentList(); | |
// Populate the argument values. | |
args->SetString(0, insides); | |
// Send the process message to the render process. | |
// Use PID_BROWSER instead when sending a message to the browser process. | |
browser->SendProcessMessage(PID_BROWSER, msg); | |
} | |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
///////////////////NICE FUNCTIONS/////////////////////////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
static void cb_nice_recv(NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer data) | |
{ | |
if (len == 1 && buf[0] == '\0') | |
jprint("failed while passing nicetext"); | |
jprint(g_strdup_printf("%.*s", len, buf)); | |
} | |
static void | |
cb_new_selected_pair(NiceAgent *agent, guint stream_id, | |
guint component_id, gchar *lfoundation, | |
gchar *rfoundation, gpointer data) | |
{ | |
jprint(g_strdup_printf("SIGNAL: selected pair %s %s", lfoundation, rfoundation)); | |
} | |
static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data) | |
{ | |
gchar *sdp, *sdp64; | |
gchar *senddata = NULL; | |
jprint("SIGNAL candidate gathering done"); | |
// Candidate gathering is done. Send our local candidates on stdout | |
// Listen on stdin for the remote candidate list | |
/*printf("Enter remote data (single line, no wrapping):\n"); | |
g_io_add_watch(io_stdin, G_IO_IN, stdin_remote_info_cb, agent); | |
printf("> "); | |
fflush (stdout);*/ | |
// Candidate gathering is done. Send our local candidates on stdout | |
jprint("Copy this line to remote client:"); | |
sdp = nice_agent_generate_local_sdp (agent); | |
sdp64 = g_base64_encode ((const guchar *)sdp, strlen (sdp)); | |
senddata = g_strdup_printf("\n %s\n", sdp64); | |
SendtoRender("NiceData", senddata); | |
g_free (sdp); | |
g_free (sdp64); | |
if (senddata) | |
g_free(senddata); | |
SendtoBoolRender("listening", TRUE); | |
// Listen on stdin for the remote candidate list | |
printf("Enter remote data (single line, no wrapping):\n"); | |
printf("> "); | |
fflush (stdout); | |
while (!exit_thread) { | |
//GIOStatus s = g_io_channel_read_line (io_stdin, &line, NULL, NULL, NULL); | |
if (NiceCand.c_str() != NULL && NiceCand != "") { | |
jprint(NiceCand.c_str()); | |
gsize sdp_len; | |
sdp = (gchar *) g_base64_decode (NiceCand.c_str(), &sdp_len); | |
// Parse remote candidate list and set it on the agent | |
if (sdp && nice_agent_parse_remote_sdp (agent, sdp) > 0) { | |
g_free (sdp); | |
NiceCand = ""; | |
break; | |
} else { | |
fprintf(stderr, "ERROR: failed to parse remote data\n"); | |
jprint("ERROR: failed to parse remote data"); | |
jprint("Enter remote data (single line, no wrapping):"); | |
fflush (stdout); | |
NiceCand = ""; | |
} | |
g_free (sdp); | |
} else if (NiceCand == "") { | |
#if defined(__unix__) || defined(__unix) | |
usleep (100000); | |
#else | |
Sleep (100); | |
#endif | |
} | |
} | |
jprint("waiting for state READY or FAILED signal..."); | |
if (exit_thread) { | |
g_object_unref(agent); | |
g_main_loop_quit (gloop); | |
} | |
} | |
static void | |
cb_component_state_changed(NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer data) | |
{ | |
jprint(g_strdup_printf("SIGNAL: state changed %d %d %s[%d]", | |
stream_id, component_id, state_name[state], state)); | |
if (state == NICE_COMPONENT_STATE_READY) { | |
SendtoBoolRender("listening", FALSE); | |
NiceCandidate *local, *remote; | |
// Get current selected candidate pair and print IP address used | |
if (nice_agent_get_selected_pair (agent, stream_id, component_id, | |
&local, &remote)) { | |
jprint("got pair"); | |
gchar ipaddr[INET6_ADDRSTRLEN]; | |
nice_address_to_string(&local->addr, ipaddr); | |
jprint(g_strdup_printf("\nNegotiation complete: ([%s]:%d,", | |
ipaddr, nice_address_get_port(&local->addr))); | |
nice_address_to_string(&remote->addr, ipaddr); | |
jprint(g_strdup_printf(" [%s]:%d)\n", ipaddr, nice_address_get_port(&remote->addr))); | |
} | |
// Listen to stdin and send data written to it | |
SendtoBoolRender("textlistening", TRUE); | |
jprint("Send lines to remote (Ctrl-D to quit):"); | |
fflush (stdout); | |
while (!exit_thread) { | |
if (NiceText != "") { | |
nice_agent_send(agent, stream_id, 1, strlen(NiceText.c_str()), NiceText.c_str()); | |
fflush (stdout); | |
NiceText = ""; | |
} else if (NiceText == "") { | |
#if defined(__unix__) || defined(__unix) | |
usleep (100000); | |
#else | |
Sleep (100); | |
#endif | |
} | |
} | |
} else if (state == NICE_COMPONENT_STATE_FAILED) { | |
jprint("Negotiation Something failed"); | |
g_main_loop_quit (gloop); | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef BREST_H_ | |
#define BREST_H_ | |
#include "bareboneshandler.h" | |
CefRefPtr<BareBonesHandler> cf_handler; | |
std::string binding = "Yet not changed"; | |
std::string NiceData; | |
void jprint(const gchar *data); | |
void SendtoRender(gchar *name, gchar *insides); | |
void SendtoBoolRender(gchar *name, gboolean insides); | |
void SendtoBrowser(gchar *name, std::string insides); | |
gboolean listening; | |
gboolean textlistening; ///BEWARE those are globals and can affect another browser windows, if there's any! | |
LRESULT CALLBACK WinProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam); | |
static void * example_thread(void *data); | |
static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, | |
gpointer data); | |
static void cb_new_selected_pair(NiceAgent *agent, guint stream_id, | |
guint component_id, gchar *lfoundation, | |
gchar *rfoundation, gpointer data); | |
static void cb_component_state_changed(NiceAgent *agent, guint stream_id, | |
guint component_id, guint state, | |
gpointer data); | |
static void cb_nice_recv(NiceAgent *agent, guint stream_id, guint component_id, | |
guint len, gchar *buf, gpointer data); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment