4
2
Fork 0

working webrtc

pull/43/head
Sudharshan S. 2019-05-26 09:21:24 +08:00
parent fe2f10fecf
commit 1d4d369b6e
Signed by: sudharshan
GPG Key ID: C861C97AAF3D9559
6 changed files with 64 additions and 62 deletions

View File

@ -43,6 +43,8 @@ target 'Runner' do
# Custom Pods
source 'https://github.com/CocoaPods/Specs.git'
pod 'GoogleWebRTC'
pod 'Just'
pod 'PercentEncoder'
# Flutter Pods
generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')

View File

@ -281,6 +281,8 @@
"${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework",
"${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
"${PODS_ROOT}/GoogleWebRTC/Frameworks/frameworks/WebRTC.framework",
"${BUILT_PRODUCTS_DIR}/Just/Just.framework",
"${BUILT_PRODUCTS_DIR}/PercentEncoder/PercentEncoder.framework",
"${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework",
"${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework",
);
@ -289,6 +291,8 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Just.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PercentEncoder.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework",
);

View File

@ -11,8 +11,8 @@ import WebRTC
public enum RTCWrapperState {
case disconnected
case ready
case connected
case connecting
}
class PeerConnectionWrapper: NSObject{
@ -53,7 +53,7 @@ class PeerConnectionWrapper: NSObject{
public func connect() {
if let peerConnection = self.peerConnection {
self.state = .connected
self.state = .connecting
let localStream = self.localStream()
peerConnection.add(localStream)
}
@ -80,6 +80,7 @@ class PeerConnectionWrapper: NSObject{
print(error)
} else {
// Use the sdp generated
self?.handleLocalSdpSet(sdp: sdp)
self?.signalingApiProvider?.postDataToUser(userId: userId, deviceId: deviceId, data: sdp!.sdp, event: "offer")
}
})
@ -100,7 +101,7 @@ class PeerConnectionWrapper: NSObject{
} else {
// handle the remote sdp
this.handleRemoteDescriptionSet()
this.state = .ready
this.state = .connected
}
})
}
@ -108,7 +109,7 @@ class PeerConnectionWrapper: NSObject{
public func createAnswerForOffer(userId: String, deviceId: String, remoteSdp: String) {
if let peerConnection = self.peerConnection {
let sessionDescription = RTCSessionDescription.init(type: .answer, sdp: remoteSdp)
let sessionDescription = RTCSessionDescription.init(type: .offer, sdp: remoteSdp)
peerConnection.setRemoteDescription(sessionDescription, completionHandler: { [weak self] (error) in
// Exit if this object doesn't exist anymore cause it is a weak link
guard let this = self else { return }
@ -119,6 +120,7 @@ class PeerConnectionWrapper: NSObject{
} else {
// handle the remote sdp
this.handleRemoteDescriptionSet()
// create answer
peerConnection.answer(for: this.channelConstraint, completionHandler:
{ (sdp, error) in
@ -127,8 +129,9 @@ class PeerConnectionWrapper: NSObject{
print(error)
} else {
// handle generated local sdp
self?.handleLocalSdpSet(sdp: sdp)
self?.signalingApiProvider?.postDataToUser(userId: userId, deviceId: deviceId, data: sdp!.sdp, event: "answer")
this.state = .ready
this.state = .connected
}
})
}
@ -159,6 +162,17 @@ private extension PeerConnectionWrapper {
self.peerConnection = self.connectionFactory?.peerConnection(with: configuration, constraints: self.connectionConstraint, delegate: self)
}
func handleLocalSdpSet(sdp: RTCSessionDescription?) {
guard let sdp = sdp else{
return
}
self.peerConnection?.setLocalDescription(sdp, completionHandler: {[weak self] (error) in
guard let _ = self, let error = error else { return }
print(error)
})
}
func handleRemoteDescriptionSet() {
for iceCandidate in self.remoteIceCandidates {
self.peerConnection?.add(iceCandidate)
@ -204,7 +218,7 @@ extension PeerConnectionWrapper: RTCPeerConnectionDelegate {
}
func peerConnection(_ peerConnection: RTCPeerConnection, didGenerate candidate: RTCIceCandidate) {
let candidateString = "\(candidate.sdp)-\(candidate.sdpMLineIndex)-\(candidate.sdpMid ?? "")"
let candidateString = "\(candidate.sdp)::\(candidate.sdpMLineIndex)::\(candidate.sdpMid ?? "")"
self.signalingApiProvider?.postDataToUser(userId: remoteUserId!, deviceId: remoteDeviceId!, data: candidateString, event: "ice-candidate")
}

View File

@ -8,6 +8,7 @@
import Foundation
import WebRTC
import PercentEncoder
class PeerManager: NSObject {
// WebRTC initialization
@ -30,6 +31,7 @@ class PeerManager: NSObject {
public func initializeToken(authToken: String) {
self.signalingApiProvider = SignalingApiProvider(authToken: authToken)
self.eventSource = EventSource(url: "http://localhost/signal/subscribe?token=\(authToken)")
initialiseEventSource()
}
public func join(conversationId: String) {
@ -42,8 +44,6 @@ class PeerManager: NSObject {
}
for user in userList {
whitePeerList.append(user)
let deviceOpList = signalingApiProvider?.getUserDevices(userId: user)
guard let deviceList = deviceOpList else {
@ -53,7 +53,10 @@ class PeerManager: NSObject {
for device in deviceList {
let connection: PeerConnectionWrapper = PeerConnectionWrapper(connectionFactory: self.connectionFactory!, signalingApiProvider: self.signalingApiProvider!, remoteUserId: user, remoteDeviceId: device)
self.peerList["\(user)-\(device)"] = connection
self.peerList["\(user):\(device)"] = connection
whitePeerList.append("\(user):\(device)")
connection.connect()
connection.createOffer(userId: user, deviceId: device)
}
}
@ -77,7 +80,6 @@ class PeerManager: NSObject {
private extension PeerManager {
func initialiseEventSource() {
eventSource?.addEventListener("offer") { (id, event, data) in
print(data!)
guard let id = id, let data = data else {
// Incorrect packet type error
return
@ -86,7 +88,7 @@ private extension PeerManager {
// Handling offers, if in list accept
if self.whitePeerList.contains(id) {
// Split id into user and device
let idArr = id.components(separatedBy: "-")
let idArr = id.components(separatedBy: ":")
// Check id format
if idArr.count != 2 {
@ -94,12 +96,16 @@ private extension PeerManager {
return
}
// Formatting data
let decoded_data = PercentEncoding.decodeURI.evaluate(string: data)
print("OFFER!")
let connection: PeerConnectionWrapper = PeerConnectionWrapper(connectionFactory: self.connectionFactory!, signalingApiProvider: self.signalingApiProvider!, remoteUserId: idArr[0], remoteDeviceId: idArr[1])
self.peerList[id] = connection
connection.createAnswerForOffer(userId: idArr[0], deviceId: idArr[1], remoteSdp: data)
connection.connect()
connection.createAnswerForOffer(userId: idArr[0], deviceId: idArr[1], remoteSdp: decoded_data)
}
}
@ -112,9 +118,13 @@ private extension PeerManager {
// Handling answers, if in list accept
if self.whitePeerList.contains(id) {
// Formatting data
let decoded_data = PercentEncoding.decodeURI.evaluate(string: data)
print("ANSWER")
let connection: PeerConnectionWrapper = self.peerList[id]!
connection.handleAnswer(remoteSdp: data)
connection.connect()
connection.handleAnswer(remoteSdp: decoded_data)
}
}
@ -129,7 +139,12 @@ private extension PeerManager {
if self.whitePeerList.contains(id) {
let connection: PeerConnectionWrapper = self.peerList[id]!
let dataArr = data.components(separatedBy: "-")
// Formatting data
let decoded_data = PercentEncoding.decodeURI.evaluate(string: data)
print("ICE!")
let dataArr = decoded_data.components(separatedBy: "::")
// Check dataArr size of 3
if dataArr.count != 3 {
@ -143,7 +158,7 @@ private extension PeerManager {
return
}
let iceCandidate = RTCIceCandidate(sdp: dataArr[0], sdpMLineIndex: sdpMLineIndex, sdpMid: dataArr[1])
let iceCandidate = RTCIceCandidate(sdp: dataArr[0], sdpMLineIndex: sdpMLineIndex, sdpMid: dataArr[2])
connection.addIceCandidate(iceCandidate: iceCandidate)
}
}

View File

@ -8,6 +8,7 @@
import Foundation
import WebRTC
import Just
class SignalingApiProvider: NSObject {
var authToken: String?
@ -22,18 +23,13 @@ class SignalingApiProvider: NSObject {
}
public func getUserDevices(userId: String) -> [String]? {
let url: URL = URL(string: "http://localhost/signal/user/\(userId)/devices")!
var deviceList: [String] = []
var request = URLRequest(url: url)
request.addValue("Bearer \(authToken ?? "0")", forHTTPHeaderField: "Authorization")
request.httpMethod = "GET"
let response = Just.get("http://localhost/signal/user/\(userId)/devices",
headers: ["Authorization": "Bearer \(authToken ?? "0")"])
var response: URLResponse?
do {
let dataVal = try NSURLConnection.sendSynchronousRequest(request, returning: &response)
if(response.ok) {
do {
if let jsonResult = try JSONSerialization.jsonObject(with: dataVal, options: []) as? [String] {
if let jsonResult = try JSONSerialization.jsonObject(with: response.content!, options: []) as? [String] {
// convert this to an array of strings
for device in jsonResult {
deviceList.append(device)
@ -47,26 +43,18 @@ class SignalingApiProvider: NSObject {
} catch let error as NSError {
print(error.localizedDescription)
}
} catch let error as NSError {
print(error.localizedDescription)
}
return nil
}
public func getConversationUsers(conversationId: String) -> [String]? {
let url: URL = URL(string: "http://localhost/core/user/conversation/\(conversationId)/member")!
var userList: [String] = []
var request = URLRequest(url: url)
request.addValue("Bearer \(authToken ?? "0")", forHTTPHeaderField: "Authorization")
request.httpMethod = "GET"
let response = Just.get("http://localhost/core/user/conversation/\(conversationId)/member",
headers: ["Authorization": "Bearer \(authToken ?? "0")"])
var response: URLResponse?
do {
let dataVal = try NSURLConnection.sendSynchronousRequest(request, returning: &response)
if (response.ok) {
do {
if let jsonResult = try JSONSerialization.jsonObject(with: dataVal, options: []) as? [Any] {
if let jsonResult = try JSONSerialization.jsonObject(with: response.content!, options: []) as? [Any] {
// Need code to convert this to an array of strings
for user in jsonResult {
if let userObject = user as? [String: String] {
@ -84,34 +72,14 @@ class SignalingApiProvider: NSObject {
} catch let error as NSError {
print(error.localizedDescription)
}
} catch let error as NSError {
print(error.localizedDescription)
}
return nil
}
// CHECK FOR WHEN DEVICE IS UNAVAILABLE
public func postDataToUser(userId: String, deviceId: String, data: String, event: String) {
let url: URL = URL(string: "http://localhost/signal/user/\(userId)/device/\(deviceId)")!
// prepare json data
let json: [String: Any] = ["event": event, "data": data]
print(json)
let jsonData = try? JSONSerialization.data(withJSONObject: json)
var request = URLRequest(url: url)
request.addValue("Bearer \(authToken ?? "0")", forHTTPHeaderField: "Authorization")
request.httpMethod = "POST"
request.httpBody = jsonData
var response: URLResponse?
do {
let _ = try NSURLConnection.sendSynchronousRequest(request, returning: &response)
} catch let error as NSError {
print(error.localizedDescription)
}
Just.post("http://localhost/signal/user/\(userId)/device/\(deviceId)",
json: ["event": event, "data": data],
headers: ["Authorization": "Bearer \(authToken ?? "0")"])
}
}

View File

@ -7,7 +7,6 @@ import "package:rxdart/rxdart.dart";
import "package:http/http.dart" as http;
import "../models/ping_model.dart";
import "../models/user_model.dart";
import "../services/login_manager.dart";
import "../resources/contact_api_provider.dart";
import "../../settings.dart";