int libwebrtc_set_offer( struct libwebrtc_connection* conn, const char* sdp ) { ILibWrapper_WebRTC_Connection connection = (ILibWrapper_WebRTC_Connection)conn; void* user_data = NULL; libwebrtc_context* ctx = NULL; ILibWrapper_WebRTC_Connection_GetUserData(connection, (void**)&ctx, NULL, &user_data); assert( ctx != NULL ); // Microstack requires at least one candidate std::string tmp; if( strstr(sdp, "a=candidate") == NULL ) { tmp = sdp; tmp += "a=candidate:0 1 UDP 2128609534 0.0.0.0 0 typ host\n"; sdp = tmp.c_str(); } char* offer = ILibWrapper_WebRTC_Connection_SetOffer(connection, (char*)sdp, strlen(sdp), &WebRTCOnIceCandidate); if( offer == NULL ) return 0; // always send this offer, as the callback will only send additianal candidates ctx->callback(ctx, conn, NULL, LWRTC_CALLBACK_LOCAL_DESCRIPTION, user_data, offer, strlen(offer)); return 1; }
// this is called for each ice candidate. if candidate is null, no additional candidates could be found. void WebRTCOnIceCandidate(ILibWrapper_WebRTC_Connection webRTCConnection, struct sockaddr_in6* candidate) { assert(webRTCConnection != NULL); void* user_data = NULL; libwebrtc_context* ctx = NULL; libwebrtc_connection* conn = (libwebrtc_connection*)webRTCConnection; ILibWrapper_WebRTC_Connection_GetUserData(webRTCConnection, (void**)&ctx, NULL, &user_data); // no additional candidates found. if( candidate == NULL ) return; char* offer = ILibWrapper_WebRTC_Connection_AddServerReflexiveCandidateToLocalSDP( webRTCConnection, candidate ); if( offer == NULL ) { ctx->callback(ctx, conn, NULL, LWRTC_CALLBACK_ERROR, user_data, NULL, 0 ); LOG("Offer failed, closing socket\n"); return; } free(offer); char address[225]; ILibInet_ntop2((struct sockaddr*)candidate, address, 255); const char* candidateFormat = "candidate:%d %d UDP %d %s %u typ host"; char buf[255] = {0}; snprintf(buf, sizeof(buf), candidateFormat, 0, 1, 2128609535-1, address, ntohs(candidate->sin6_port)); buf[sizeof(buf)-1] = 0; ctx->callback(ctx, conn, NULL, LWRTC_CALLBACK_ICE_CANDIDATE, user_data, buf, strlen(buf) ); }
int libwebrtc_add_ice_candidate( struct libwebrtc_connection* conn, const char* candidate ) { ILibWrapper_WebRTC_Connection connection = (ILibWrapper_WebRTC_Connection)conn; // updating the block seems to be causing some issues. disabled for now. // if(true)return 1; void* user_data = NULL; libwebrtc_context* ctx = NULL; ILibWrapper_WebRTC_Connection_GetUserData(connection, (void**)&ctx, NULL, &user_data); assert( ctx != NULL ); char address[255] = {0}; int port = 0; // candidate:0 1 UDP 2128609534 0.0.0.0 0 typ host sscanf(candidate, "%*s %*d %*s %*d %s %d %*s %*s", address, &port); // todo, parse candidate into struct sockaddr_in6 and add to the offer... char* offer = ILibWrapper_WebRTC_Connection_AddServerReflexiveCandidateToRemoteSDP(connection, address, port ); ::libwebrtc_set_answer(conn, offer ); free(offer); return 1; }
void libwebrtc_close_connection( struct libwebrtc_connection* conn ) { ILibWrapper_WebRTC_Connection connection = (ILibWrapper_WebRTC_Connection)conn; void* user_data = NULL; libwebrtc_context* ctx = NULL; ILibWrapper_WebRTC_Connection_GetUserData(connection, (void**)&ctx, NULL, &user_data); assert( ctx != NULL ); // this will trigger the callback for any existing channels. ILibWrapper_WebRTC_Connection_Disconnect(connection); // the connection object is now destroyed }
struct libwebrtc_data_channel* libwebrtc_create_channel( struct libwebrtc_connection* c, const char* name ) { ILibWrapper_WebRTC_Connection connection = (ILibWrapper_WebRTC_Connection)c; if( ! ILibWrapper_WebRTC_Connection_IsConnected( connection ) ) return NULL; ILibWrapper_WebRTC_DataChannel* channel = ILibWrapper_WebRTC_DataChannel_Create(connection, (char*)name, strlen(name), &WebRTCOnDataChannelAck ); // Initially use parent user_data ILibWrapper_WebRTC_Connection_GetUserData(connection, NULL, NULL, &channel->userData); return (libwebrtc_data_channel*)channel; }
// this is called when a channel receives data. void WebRTCOnDataChannelData(struct ILibWrapper_WebRTC_DataChannel* dataChannel, char* data, int dataLen) { assert(dataChannel != NULL); assert(data != NULL); assert(dataLen > 0); void* user_data = dataChannel->userData; libwebrtc_context* ctx = NULL; libwebrtc_connection* conn = (libwebrtc_connection*)dataChannel->parent; libwebrtc_data_channel* channel = (libwebrtc_data_channel*)dataChannel; ILibWrapper_WebRTC_Connection_GetUserData(dataChannel->parent, (void**)&ctx, NULL, NULL);//&user_data); assert( ctx != NULL ); ctx->callback( ctx, conn, channel, LWRTC_CALLBACK_CHANNEL_RECEIVE, user_data, data, dataLen ); }
void libwebrtc_close_channel( struct libwebrtc_data_channel* channel ) { ILibWrapper_WebRTC_DataChannel* dataChannel = (ILibWrapper_WebRTC_DataChannel*)channel; void* user_data = dataChannel->userData; libwebrtc_context* ctx = NULL; //libwebrtc_connection* conn = (libwebrtc_connection*)dataChannel->parent; ILibWrapper_WebRTC_Connection_GetUserData(dataChannel->parent, (void**)&ctx, NULL, &user_data); assert( ctx != NULL ); // still unsure if this will trigger a channelClosed or not. ILibWrapper_WebRTC_DataChannel_Close(dataChannel); // uncomment this if its not triggered by above... //ctx->callback( ctx, conn, channel, LWRTC_CALLBACK_CHANNEL_CLOSED, user_data, 0, 0 ); }
// This is called when the DataChannel is closed void WebRTCOnDataChannelClosed(ILibWrapper_WebRTC_DataChannel *dataChannel) { assert(dataChannel != NULL); void* user_data = dataChannel->userData; libwebrtc_context* ctx = NULL; libwebrtc_connection* conn = (libwebrtc_connection*)dataChannel->parent; libwebrtc_data_channel* channel = (libwebrtc_data_channel*)dataChannel; ILibWrapper_WebRTC_Connection_GetUserData(dataChannel->parent, (void**)&ctx, NULL, NULL);//&user_data); if( ! ctx ) return; // NOTE: When channels are auto-closed due to connection being destroyed, the channel_closed callback will occur AFTER the connection closed callback... ctx->callback( ctx, conn, channel, LWRTC_CALLBACK_CHANNEL_CLOSED, user_data, dataChannel->channelName, strlen(dataChannel->channelName) ); }
// This is called when the remote ACK's our DataChannel creation request void WebRTCOnDataChannelAck(ILibWrapper_WebRTC_DataChannel *dataChannel) { assert( dataChannel != NULL ); assert( dataChannel->parent != NULL ); void* user_data = dataChannel->userData; libwebrtc_context* ctx = NULL; libwebrtc_connection* conn = (libwebrtc_connection*)dataChannel->parent; libwebrtc_data_channel* channel = (libwebrtc_data_channel*)dataChannel; ILibWrapper_WebRTC_Connection_GetUserData(dataChannel->parent, (void**)&ctx, NULL, NULL);//&Nuser_data); assert( ctx != NULL ); dataChannel->OnBinaryData = &WebRTCOnDataChannelData; dataChannel->OnClosed = &WebRTCOnDataChannelClosed; ctx->callback( ctx, conn, channel, LWRTC_CALLBACK_CHANNEL_CONNECTED, user_data, dataChannel->channelName, strlen(dataChannel->channelName) ); }
// If we launched this sample with "STUN", then this is called when a STUN candidate is found while setting an offer void CandidateSink(ILibWrapper_WebRTC_Connection connection, struct sockaddr_in6* candidate) { printf(red"candidatesink!\n"rst); SimpleRendezvousServer sender; SimpleRendezvousServerToken token; char *sdp = ILibWrapper_WebRTC_Connection_AddServerReflexiveCandidateToLocalSDP(connection, candidate); ILibWrapper_WebRTC_Connection_GetUserData(connection, &sender, &token, NULL); if(SimpleRendezvousServer_WebSocket_IsWebSocket(token)==0) { printf(red"ws is ws(token?)\n"rst); SimpleRendezvousServer_Respond(sender, token, 1, sdp, strlen(sdp), ILibAsyncSocket_MemoryOwnership_CHAIN); // Send the SDP to the remote side } else { printf(red"not token?\n"rst); SimpleRendezvousServer_WebSocket_Send(token, SimpleRendezvousServer_WebSocket_DataType_TEXT, sdp, strlen(sdp), ILibAsyncSocket_MemoryOwnership_CHAIN, SimpleRendezvousServer_FragmentFlag_Complete); } }
// This is called when the remote side creates a data channel void WebRTCDataChannelAccept(ILibWrapper_WebRTC_Connection webRTCConnection, ILibWrapper_WebRTC_DataChannel *dataChannel) { assert( webRTCConnection != NULL ); assert( dataChannel != NULL ); void* user_data = NULL; libwebrtc_context* ctx = NULL; libwebrtc_connection* conn = (libwebrtc_connection*)webRTCConnection; libwebrtc_data_channel* channel = (libwebrtc_data_channel*)dataChannel; ILibWrapper_WebRTC_Connection_GetUserData(webRTCConnection, (void**)&ctx, NULL, &user_data); assert( ctx != NULL ); dataChannel->OnBinaryData = &WebRTCOnDataChannelData; dataChannel->OnClosed = &WebRTCOnDataChannelClosed; // use the parent user_data initially. dataChannel->userData = user_data; ctx->callback( ctx, conn, channel, LWRTC_CALLBACK_CHANNEL_ACCEPTED, user_data, dataChannel->channelName, strlen(dataChannel->channelName) ); }
int libwebrtc_create_offer( struct libwebrtc_connection* c ) { ILibWrapper_WebRTC_Connection connection = (ILibWrapper_WebRTC_Connection)c; void* user_data = NULL; libwebrtc_context* ctx = NULL; ILibWrapper_WebRTC_Connection_GetUserData(connection, (void**)&ctx, NULL, &user_data); assert( ctx != NULL ); char* offer = ILibWrapper_WebRTC_Connection_GenerateOffer(connection, &WebRTCOnIceCandidate ); if( offer == NULL ) return 0; // always send this offer, as the callback will only send additianal candidates if( ctx->callback(ctx, c, NULL, LWRTC_CALLBACK_LOCAL_DESCRIPTION, user_data, offer, strlen(offer)) ) { return 0; } return 1; }
void PassiveCandidateSink(ILibWrapper_WebRTC_Connection connection, struct sockaddr_in6* candidate) { printf("While generating an offer?\n"rst); SimpleRendezvousServer sender; SimpleRendezvousServerToken token; char *offer; char *encodedOffer; int encodedOfferLen; char *h1; ILibWrapper_WebRTC_Connection_GetUserData(connection, &sender, &token, (void**)&h1); offer = ILibWrapper_WebRTC_Connection_AddServerReflexiveCandidateToLocalSDP(connection, candidate); printf(green"ofer: \n %s\n"rst,offer); encodedOfferLen = ILibBase64Encode((unsigned char*)offer, strlen(offer),(unsigned char**)&encodedOffer); h1 = ILibString_Replace(passiveHtmlBody, passiveHtmlBodyLength, "/*{{{SDP}}}*/", 13, encodedOffer, encodedOfferLen); free(offer); free(encodedOffer); SimpleRendezvousServer_Respond(sender, token, 1, h1, strlen(h1), ILibAsyncSocket_MemoryOwnership_CHAIN); // Send the SDP to the remote side }
int libwebrtc_set_answer( struct libwebrtc_connection* conn, const char* sdp ) { ILibWrapper_WebRTC_Connection connection = (ILibWrapper_WebRTC_Connection)conn; void* user_data = NULL; libwebrtc_context* ctx = NULL; ILibWrapper_WebRTC_Connection_GetUserData(connection, (void**)&ctx, NULL, &user_data); assert( ctx != NULL ); // Microstack requires at least one candidate std::string tmp; if( strstr(sdp, "a=candidate") == NULL ) { tmp = sdp; tmp += "a=candidate:0 1 UDP 2128609534 0.0.0.0 0 typ host\n"; sdp = tmp.c_str(); } char* offer = ILibWrapper_WebRTC_Connection_SetOffer(connection, (char*)sdp, strlen(sdp), NULL); // no CB as this is the answer if( offer == NULL ) return 0; return 1; }
// This is called when a WebRTC Connection is established or disconnected void WebRTCConnectionStatus(ILibWrapper_WebRTC_Connection webRTCConnection, int connected) { assert(webRTCConnection != NULL); void* user_data = NULL; libwebrtc_context* ctx = NULL; libwebrtc_connection* conn = (libwebrtc_connection*)webRTCConnection; ILibWrapper_WebRTC_Connection_GetUserData(webRTCConnection, (void**)&ctx, NULL, &user_data); assert( ctx != NULL ); if( connected ) ctx->callback( ctx, conn, NULL, LWRTC_CALLBACK_ESTABLISHED, user_data, NULL, 0); else { // TODO: We really should notify all the channels as closed as well, as we can't rely on microstack to do it as it occurs after this call. // Clear the user data from the Connection, so additional callbacks wont be fired, as an DCs that are active get closed AFTER this call. ILibWrapper_WebRTC_Connection_SetUserData(webRTCConnection, NULL, NULL, NULL); ctx->callback( ctx, conn, NULL, LWRTC_CALLBACK_DISCONNECTED, user_data, NULL, 0); // for all intensive purposes the connection object is destroyed at this point. We dont have a specific callback, // but since this was called it WILL be destroyed when this call returns. ctx->callback( ctx, conn, NULL, LWRTC_CALLBACK_DESTROY, user_data, NULL, 0); } }
__declspec(dllexport) void ILibWrapper_DLL_WebRTC_Connection_GetUserData(ILibWrapper_WebRTC_Connection connection, void **user1, void **user2, void **user3) { ILibWrapper_WebRTC_Connection_GetUserData(connection, user1, user2, user3); }