Initial commit
This commit is contained in:
25
local_pod_repo/objcTox/Classes/Private/Wrapper/OCTLogging.h
Normal file
25
local_pod_repo/objcTox/Classes/Private/Wrapper/OCTLogging.h
Normal file
@ -0,0 +1,25 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "DDLog.h"
|
||||
#undef LOG_LEVEL_DEF
|
||||
#define LOG_LEVEL_DEF LOG_LEVEL_VERBOSE
|
||||
|
||||
#define OCTLogError(frmt, ...) DDLogError((@"<%@ %p> " frmt), [self class], self, ## __VA_ARGS__)
|
||||
#define OCTLogWarn(frmt, ...) DDLogWarn((@"<%@ %p> " frmt), [self class], self, ## __VA_ARGS__)
|
||||
#define OCTLogInfo(frmt, ...) DDLogInfo((@"<%@ %p> " frmt), [self class], self, ## __VA_ARGS__)
|
||||
#define OCTLogDebug(frmt, ...) DDLogDebug((@"<%@ %p> " frmt), [self class], self, ## __VA_ARGS__)
|
||||
#define OCTLogVerbose(frmt, ...) DDLogVerbose((@"<%@ %p> " frmt), [self class], self, ## __VA_ARGS__)
|
||||
|
||||
#define OCTLogCError(frmt, obj, ...) DDLogCError((@"<%@ %p> " frmt), [obj class], obj, ## __VA_ARGS__)
|
||||
#define OCTLogCWarn(frmt, obj, ...) DDLogCWarn((@"<%@ %p> " frmt), [obj class], obj, ## __VA_ARGS__)
|
||||
#define OCTLogCInfo(frmt, obj, ...) DDLogCInfo((@"<%@ %p> " frmt), [obj class], obj, ## __VA_ARGS__)
|
||||
#define OCTLogCDebug(frmt, obj, ...) DDLogCDebug((@"<%@ %p> " frmt), [obj class], obj, ## __VA_ARGS__)
|
||||
#define OCTLogCVerbose(frmt, obj, ...) DDLogCVerbose((@"<%@ %p> " frmt), [obj class], obj, ## __VA_ARGS__)
|
||||
|
||||
#define OCTLogCCError(frmt, ...) DDLogCError((frmt), ## __VA_ARGS__)
|
||||
#define OCTLogCCWarn(frmt, ...) DDLogCWarn((frmt), ## __VA_ARGS__)
|
||||
#define OCTLogCCInfo(frmt, ...) DDLogCInfo((frmt), ## __VA_ARGS__)
|
||||
#define OCTLogCCDebug(frmt, ...) DDLogCDebug((frmt), ## __VA_ARGS__)
|
||||
#define OCTLogCCVerbose(frmt, ...) DDLogCVerbose((frmt), ## __VA_ARGS__)
|
@ -0,0 +1,63 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTTox.h"
|
||||
#import <toxcore/tox.h>
|
||||
|
||||
/**
|
||||
* Tox functions
|
||||
*/
|
||||
extern void (*_tox_self_get_public_key)(const Tox *tox, uint8_t *public_key);
|
||||
|
||||
/**
|
||||
* Callbacks
|
||||
*/
|
||||
tox_log_cb logCallback;
|
||||
tox_self_connection_status_cb connectionStatusCallback;
|
||||
tox_friend_name_cb friendNameCallback;
|
||||
tox_friend_status_message_cb friendStatusMessageCallback;
|
||||
tox_friend_status_cb friendStatusCallback;
|
||||
tox_friend_connection_status_cb friendConnectionStatusCallback;
|
||||
tox_friend_typing_cb friendTypingCallback;
|
||||
tox_friend_read_receipt_cb friendReadReceiptCallback;
|
||||
tox_friend_request_cb friendRequestCallback;
|
||||
tox_friend_message_cb friendMessageCallback;
|
||||
tox_friend_lossless_packet_cb friendLosslessPacketCallback;
|
||||
tox_file_recv_control_cb fileReceiveControlCallback;
|
||||
tox_file_chunk_request_cb fileChunkRequestCallback;
|
||||
tox_file_recv_cb fileReceiveCallback;
|
||||
tox_file_recv_chunk_cb fileReceiveChunkCallback;
|
||||
|
||||
@interface OCTTox (Private)
|
||||
|
||||
@property (assign, nonatomic) Tox *tox;
|
||||
|
||||
- (OCTToxUserStatus)userStatusFromCUserStatus:(TOX_USER_STATUS)cStatus;
|
||||
- (OCTToxConnectionStatus)userConnectionStatusFromCUserStatus:(TOX_CONNECTION)cStatus;
|
||||
- (OCTToxMessageType)messageTypeFromCMessageType:(TOX_MESSAGE_TYPE)cType;
|
||||
- (OCTToxFileControl)fileControlFromCFileControl:(TOX_FILE_CONTROL)cControl;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorInit:(TOX_ERR_NEW)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorBootstrap:(TOX_ERR_BOOTSTRAP)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorFriendAdd:(TOX_ERR_FRIEND_ADD)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorFriendDelete:(TOX_ERR_FRIEND_DELETE)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorFriendByPublicKey:(TOX_ERR_FRIEND_BY_PUBLIC_KEY)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorFriendGetPublicKey:(TOX_ERR_FRIEND_GET_PUBLIC_KEY)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorSetInfo:(TOX_ERR_SET_INFO)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorFriendGetLastOnline:(TOX_ERR_FRIEND_GET_LAST_ONLINE)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorFriendQuery:(TOX_ERR_FRIEND_QUERY)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorSetTyping:(TOX_ERR_SET_TYPING)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorFriendSendMessage:(TOX_ERR_FRIEND_SEND_MESSAGE)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorFileControl:(TOX_ERR_FILE_CONTROL)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorFileSeek:(TOX_ERR_FILE_SEEK)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorFileGet:(TOX_ERR_FILE_GET)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorFileSend:(TOX_ERR_FILE_SEND)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorFileSendChunk:(TOX_ERR_FILE_SEND_CHUNK)cError;
|
||||
+ (NSError *)createErrorWithCode:(NSUInteger)code
|
||||
description:(NSString *)description
|
||||
failureReason:(NSString *)failureReason;
|
||||
- (struct Tox_Options) cToxOptionsFromOptions:(OCTToxOptions *)options;
|
||||
+ (NSString *)binToHexString:(uint8_t *)bin length:(NSUInteger)length;
|
||||
+ (uint8_t *)hexStringToBin:(NSString *)string;
|
||||
|
||||
@end
|
2250
local_pod_repo/objcTox/Classes/Private/Wrapper/OCTTox.m
Normal file
2250
local_pod_repo/objcTox/Classes/Private/Wrapper/OCTTox.m
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,51 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTToxAV.h"
|
||||
#import <toxcore/toxav/toxav.h>
|
||||
|
||||
/**
|
||||
* ToxAV functions
|
||||
*/
|
||||
|
||||
extern ToxAV *(*_toxav_new)(Tox *tox, TOXAV_ERR_NEW *error);
|
||||
extern uint32_t (*_toxav_iteration_interval)(const ToxAV *toxAV);
|
||||
extern void (*_toxav_iterate)(ToxAV *toxAV);
|
||||
extern void (*_toxav_kill)(ToxAV *toxAV);
|
||||
|
||||
extern bool (*_toxav_call)(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL *error);
|
||||
extern bool (*_toxav_answer)(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER *error);
|
||||
extern bool (*_toxav_call_control)(ToxAV *toxAV, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error);
|
||||
|
||||
extern bool (*_toxav_audio_set_bit_rate)(ToxAV *av, uint32_t friend_number, uint32_t bit_rate, TOXAV_ERR_BIT_RATE_SET *error);
|
||||
extern bool (*_toxav_video_set_bit_rate)(ToxAV *av, uint32_t friend_number, uint32_t bit_rate, TOXAV_ERR_BIT_RATE_SET *error);
|
||||
|
||||
extern bool (*_toxav_audio_send_frame)(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME *error);
|
||||
extern bool (*_toxav_video_send_frame)(ToxAV *toxAV, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, TOXAV_ERR_SEND_FRAME *error);
|
||||
|
||||
/**
|
||||
* Callbacks
|
||||
*/
|
||||
toxav_call_cb callIncomingCallback;
|
||||
toxav_call_state_cb callStateCallback;
|
||||
toxav_audio_bit_rate_cb audioBitRateStatusCallback;
|
||||
toxav_video_bit_rate_cb videoBitRateStatusCallback;
|
||||
toxav_audio_receive_frame_cb receiveAudioFrameCallback;
|
||||
toxav_video_receive_frame_cb receiveVideoFrameCallback;
|
||||
|
||||
@interface OCTToxAV (Private)
|
||||
|
||||
@property (assign, nonatomic) ToxAV *toxAV;
|
||||
|
||||
- (BOOL)fillError:(NSError **)error withCErrorInit:(TOXAV_ERR_NEW)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorCall:(TOXAV_ERR_CALL)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorAnswer:(TOXAV_ERR_ANSWER)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorControl:(TOXAV_ERR_CALL_CONTROL)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorSetBitRate:(TOXAV_ERR_BIT_RATE_SET)cError;
|
||||
- (BOOL)fillError:(NSError **)error withCErrorSendFrame:(TOXAV_ERR_SEND_FRAME)cError;
|
||||
- (NSError *)createErrorWithCode:(NSUInteger)code
|
||||
description:(NSString *)description
|
||||
failureReason:(NSString *)failureReason;
|
||||
|
||||
@end
|
648
local_pod_repo/objcTox/Classes/Private/Wrapper/OCTToxAV.m
Normal file
648
local_pod_repo/objcTox/Classes/Private/Wrapper/OCTToxAV.m
Normal file
@ -0,0 +1,648 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTTox+Private.h"
|
||||
#import "OCTToxAV+Private.h"
|
||||
#import "OCTLogging.h"
|
||||
|
||||
ToxAV *(*_toxav_new)(Tox *tox, TOXAV_ERR_NEW *error);
|
||||
uint32_t (*_toxav_iteration_interval)(const ToxAV *toxAV);
|
||||
void (*_toxav_iterate)(ToxAV *toxAV);
|
||||
void (*_toxav_kill)(ToxAV *toxAV);
|
||||
|
||||
bool (*_toxav_call)(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL *error);
|
||||
bool (*_toxav_answer)(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER *error);
|
||||
bool (*_toxav_call_control)(ToxAV *toxAV, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error);
|
||||
|
||||
bool (*_toxav_audio_set_bit_rate)(ToxAV *av, uint32_t friend_number, uint32_t bit_rate, TOXAV_ERR_BIT_RATE_SET *error);
|
||||
bool (*_toxav_video_set_bit_rate)(ToxAV *av, uint32_t friend_number, uint32_t bit_rate, TOXAV_ERR_BIT_RATE_SET *error);
|
||||
|
||||
bool (*_toxav_audio_send_frame)(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME *error);
|
||||
bool (*_toxav_video_send_frame)(ToxAV *toxAV, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, TOXAV_ERR_SEND_FRAME *error);
|
||||
|
||||
|
||||
@interface OCTToxAV ()
|
||||
|
||||
@property (assign, nonatomic) ToxAV *toxAV;
|
||||
|
||||
@property (strong, nonatomic) dispatch_source_t timer;
|
||||
|
||||
@property (assign, nonatomic) uint64_t previousIterate;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTToxAV
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
- (instancetype)initWithTox:(OCTTox *)tox error:(NSError **)error
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (! self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
OCTLogVerbose(@"init called");
|
||||
|
||||
[self setupCFunctions];
|
||||
|
||||
TOXAV_ERR_NEW cError;
|
||||
_toxAV = _toxav_new(tox.tox, &cError);
|
||||
|
||||
[self fillError:error withCErrorInit:cError];
|
||||
|
||||
[self setupCallbacks];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)start
|
||||
{
|
||||
OCTLogVerbose(@"start method called");
|
||||
|
||||
@synchronized(self) {
|
||||
if (self.timer) {
|
||||
OCTLogWarn(@"already started");
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_queue_t queue = dispatch_queue_create("me.dvor.objcTox.OCTToxAVQueue", NULL);
|
||||
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
|
||||
|
||||
[self updateTimerIntervalIfNeeded];
|
||||
|
||||
__weak OCTToxAV *weakSelf = self;
|
||||
dispatch_source_set_event_handler(self.timer, ^{
|
||||
OCTToxAV *strongSelf = weakSelf;
|
||||
if (! strongSelf) {
|
||||
return;
|
||||
}
|
||||
|
||||
_toxav_iterate(strongSelf.toxAV);
|
||||
|
||||
[strongSelf updateTimerIntervalIfNeeded];
|
||||
});
|
||||
|
||||
dispatch_resume(self.timer);
|
||||
}
|
||||
OCTLogInfo(@"started");
|
||||
}
|
||||
|
||||
- (void)stop
|
||||
{
|
||||
OCTLogVerbose(@"stop method called");
|
||||
|
||||
@synchronized(self) {
|
||||
if (! self.timer) {
|
||||
OCTLogWarn(@"toxav isn't running, nothing to stop");
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_source_cancel(self.timer);
|
||||
self.timer = nil;
|
||||
}
|
||||
|
||||
OCTLogInfo(@"stopped");
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self stop];
|
||||
_toxav_kill(self.toxAV);
|
||||
OCTLogVerbose(@"dealloc called, toxav killed");
|
||||
}
|
||||
|
||||
#pragma mark - Call Methods
|
||||
|
||||
- (BOOL)callFriendNumber:(OCTToxFriendNumber)friendNumber audioBitRate:(OCTToxAVAudioBitRate)audioBitRate videoBitRate:(OCTToxAVVideoBitRate)videoBitRate error:(NSError **)error
|
||||
{
|
||||
TOXAV_ERR_CALL cError;
|
||||
BOOL status = _toxav_call(self.toxAV, friendNumber, audioBitRate, videoBitRate, &cError);
|
||||
|
||||
[self fillError:error withCErrorCall:cError];
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
- (BOOL)answerIncomingCallFromFriend:(OCTToxFriendNumber)friendNumber audioBitRate:(OCTToxAVAudioBitRate)audioBitRate videoBitRate:(OCTToxAVVideoBitRate)videoBitrate error:(NSError **)error
|
||||
{
|
||||
TOXAV_ERR_ANSWER cError;
|
||||
BOOL status = _toxav_answer(self.toxAV, friendNumber, audioBitRate, videoBitrate, &cError);
|
||||
|
||||
[self fillError:error withCErrorAnswer:cError];
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
- (BOOL)sendCallControl:(OCTToxAVCallControl)control toFriendNumber:(OCTToxFriendNumber)friendNumber error:(NSError **)error
|
||||
{
|
||||
TOXAV_CALL_CONTROL cControl;
|
||||
|
||||
switch (control) {
|
||||
case OCTToxAVCallControlResume:
|
||||
cControl = TOXAV_CALL_CONTROL_RESUME;
|
||||
break;
|
||||
case OCTToxAVCallControlPause:
|
||||
cControl = TOXAV_CALL_CONTROL_PAUSE;
|
||||
break;
|
||||
case OCTToxAVCallControlCancel:
|
||||
cControl = TOXAV_CALL_CONTROL_CANCEL;
|
||||
break;
|
||||
case OCTToxAVCallControlMuteAudio:
|
||||
cControl = TOXAV_CALL_CONTROL_MUTE_AUDIO;
|
||||
break;
|
||||
case OCTToxAVCallControlUnmuteAudio:
|
||||
cControl = TOXAV_CALL_CONTROL_UNMUTE_AUDIO;
|
||||
break;
|
||||
case OCTToxAVCallControlHideVideo:
|
||||
cControl = TOXAV_CALL_CONTROL_HIDE_VIDEO;
|
||||
break;
|
||||
case OCTToxAVCallControlShowVideo:
|
||||
cControl = TOXAV_CALL_CONTROL_SHOW_VIDEO;
|
||||
break;
|
||||
}
|
||||
|
||||
TOXAV_ERR_CALL_CONTROL cError;
|
||||
|
||||
BOOL status = _toxav_call_control(self.toxAV, friendNumber, cControl, &cError);
|
||||
|
||||
[self fillError:error withCErrorControl:cError];
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#pragma mark - Controlling bit rates
|
||||
|
||||
- (BOOL)setAudioBitRate:(OCTToxAVAudioBitRate)bitRate force:(BOOL)force forFriend:(OCTToxFriendNumber)friendNumber error:(NSError **)error
|
||||
{
|
||||
TOXAV_ERR_BIT_RATE_SET cError;
|
||||
|
||||
BOOL status = _toxav_audio_set_bit_rate(self.toxAV, friendNumber, bitRate, &cError);
|
||||
|
||||
[self fillError:error withCErrorSetBitRate:cError];
|
||||
|
||||
OCTLogVerbose(@"setAudioBitRate:%lu, force:%d, friend:%d", (long)bitRate, force, friendNumber);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
- (BOOL)setVideoBitRate:(OCTToxAVVideoBitRate)bitRate force:(BOOL)force forFriend:(OCTToxFriendNumber)friendNumber error:(NSError **)error
|
||||
{
|
||||
TOXAV_ERR_BIT_RATE_SET cError;
|
||||
|
||||
BOOL status = _toxav_video_set_bit_rate(self.toxAV, friendNumber, bitRate, &cError);
|
||||
|
||||
[self fillError:error withCErrorSetBitRate:cError];
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#pragma mark - Sending frames
|
||||
- (BOOL)sendAudioFrame:(OCTToxAVPCMData *)pcm sampleCount:(OCTToxAVSampleCount)sampleCount
|
||||
channels:(OCTToxAVChannels)channels sampleRate:(OCTToxAVSampleRate)sampleRate
|
||||
toFriend:(OCTToxFriendNumber)friendNumber error:(NSError **)error
|
||||
{
|
||||
// TOXAUDIO: -outgoing-audio-
|
||||
TOXAV_ERR_SEND_FRAME cError;
|
||||
|
||||
BOOL status = _toxav_audio_send_frame(self.toxAV, friendNumber,
|
||||
pcm, sampleCount,
|
||||
channels, sampleRate, &cError);
|
||||
|
||||
[self fillError:error withCErrorSendFrame:cError];
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
- (BOOL)sendVideoFrametoFriend:(OCTToxFriendNumber)friendNumber
|
||||
width:(OCTToxAVVideoWidth)width height:(OCTToxAVVideoHeight)height
|
||||
yPlane:(OCTToxAVPlaneData *)yPlane uPlane:(OCTToxAVPlaneData *)uPlane
|
||||
vPlane:(OCTToxAVPlaneData *)vPlane
|
||||
error:(NSError **)error
|
||||
{
|
||||
TOXAV_ERR_SEND_FRAME cError;
|
||||
BOOL status = _toxav_video_send_frame(self.toxAV, friendNumber, width, height, yPlane, uPlane, vPlane, &cError);
|
||||
|
||||
[self fillError:error withCErrorSendFrame:cError];
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)setupCFunctions
|
||||
{
|
||||
_toxav_new = toxav_new;
|
||||
_toxav_iteration_interval = toxav_iteration_interval;
|
||||
_toxav_iterate = toxav_iterate;
|
||||
_toxav_kill = toxav_kill;
|
||||
|
||||
_toxav_call = toxav_call;
|
||||
_toxav_answer = toxav_answer;
|
||||
_toxav_call_control = toxav_call_control;
|
||||
|
||||
_toxav_audio_set_bit_rate = toxav_audio_set_bit_rate;
|
||||
_toxav_video_set_bit_rate = toxav_video_set_bit_rate;
|
||||
|
||||
_toxav_audio_send_frame = toxav_audio_send_frame;
|
||||
_toxav_video_send_frame = toxav_video_send_frame;
|
||||
}
|
||||
|
||||
- (void)setupCallbacks
|
||||
{
|
||||
toxav_callback_call(_toxAV, callIncomingCallback, (__bridge void *)(self));
|
||||
toxav_callback_call_state(_toxAV, callStateCallback, (__bridge void *)(self));
|
||||
toxav_callback_audio_bit_rate(_toxAV, audioBitRateStatusCallback, (__bridge void *)(self));
|
||||
toxav_callback_video_bit_rate(_toxAV, videoBitRateStatusCallback, (__bridge void *)(self));
|
||||
toxav_callback_audio_receive_frame(_toxAV, receiveAudioFrameCallback, (__bridge void *)(self));
|
||||
toxav_callback_video_receive_frame(_toxAV, receiveVideoFrameCallback, (__bridge void *)(self));
|
||||
}
|
||||
|
||||
- (BOOL)fillError:(NSError **)error withCErrorInit:(TOXAV_ERR_NEW)cError
|
||||
{
|
||||
if (! error || (cError == TOXAV_ERR_NEW_OK)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
OCTToxAVErrorInitCode code = OCTToxAVErrorInitCodeUnknown;
|
||||
NSString *description = @"Cannot initialize ToxAV";
|
||||
NSString *failureReason = nil;
|
||||
|
||||
switch (cError) {
|
||||
case TOXAV_ERR_NEW_OK:
|
||||
NSAssert(NO, @"We shouldn't be here!");
|
||||
break;
|
||||
case TOXAV_ERR_NEW_NULL:
|
||||
code = OCTToxAVErrorInitNULL;
|
||||
failureReason = @"One of the arguments to the function was NULL when it was not expected.";
|
||||
break;
|
||||
case TOXAV_ERR_NEW_MALLOC:
|
||||
code = OCTToxAVErrorInitCodeMemoryError;
|
||||
failureReason = @"Memory allocation failure while trying to allocate structures required for the A/V session.";
|
||||
break;
|
||||
case TOXAV_ERR_NEW_MULTIPLE:
|
||||
code = OCTToxAVErrorInitMultiple;
|
||||
failureReason = @"Attempted to create a second session for the same Tox instance.";
|
||||
break;
|
||||
}
|
||||
*error = [self createErrorWithCode:code description:description failureReason:failureReason];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)fillError:(NSError **)error withCErrorCall:(TOXAV_ERR_CALL)cError
|
||||
{
|
||||
if (! error || (cError == TOXAV_ERR_CALL_OK)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
OCTToxAVErrorCall code = OCTToxAVErrorCallUnknown;
|
||||
NSString *description = @"Could not make call";
|
||||
NSString *failureReason = nil;
|
||||
|
||||
switch (cError) {
|
||||
case TOXAV_ERR_CALL_OK:
|
||||
NSAssert(NO, @"We shouldn't be here!");
|
||||
break;
|
||||
case TOXAV_ERR_CALL_MALLOC:
|
||||
code = OCTToxAVErrorCallMalloc;
|
||||
failureReason = @"A resource allocation error occured while trying to create the structures required for the call.";
|
||||
break;
|
||||
case TOXAV_ERR_CALL_SYNC:
|
||||
code = OCTToxAVErrorCallSync;
|
||||
failureReason = @"Synchronization error occurred.";
|
||||
break;
|
||||
case TOXAV_ERR_CALL_FRIEND_NOT_FOUND:
|
||||
code = OCTToxAVErrorCallFriendNotFound;
|
||||
failureReason = @"The friend number did not designate a valid friend.";
|
||||
break;
|
||||
case TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED:
|
||||
code = OCTToxAVErrorCallFriendNotConnected;
|
||||
failureReason = @"The friend was valid, but not currently connected";
|
||||
break;
|
||||
case TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL:
|
||||
code = OCTToxAVErrorCallAlreadyInCall;
|
||||
failureReason = @"Attempted to call a friend while already in an audio or video call with them.";
|
||||
break;
|
||||
case TOXAV_ERR_CALL_INVALID_BIT_RATE:
|
||||
code = OCTToxAVErrorCallInvalidBitRate;
|
||||
failureReason = @"Audio or video bit rate is invalid";
|
||||
break;
|
||||
}
|
||||
|
||||
*error = [self createErrorWithCode:code description:description failureReason:failureReason];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)fillError:(NSError **)error withCErrorAnswer:(TOXAV_ERR_ANSWER)cError
|
||||
{
|
||||
if (! error || (cError == TOXAV_ERR_ANSWER_OK)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
OCTToxAVErrorAnswer code = OCTToxAVErrorAnswerUnknown;
|
||||
NSString *description = @"Could not answer call";
|
||||
NSString *failureReason = nil;
|
||||
|
||||
switch (cError) {
|
||||
case TOXAV_ERR_ANSWER_OK:
|
||||
NSAssert(NO, @"We shouldn't be here!");
|
||||
break;
|
||||
case TOXAV_ERR_ANSWER_SYNC:
|
||||
code = OCTToxAVErrorAnswerSync;
|
||||
break;
|
||||
case TOXAV_ERR_ANSWER_CODEC_INITIALIZATION:
|
||||
code = OCTToxAVErrorAnswerCodecInitialization;
|
||||
break;
|
||||
case TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING:
|
||||
code = OCTToxAVErrorAnswerFriendNotCalling;
|
||||
break;
|
||||
case TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND:
|
||||
code = OCTToxAVErrorAnswerFriendNotFound;
|
||||
break;
|
||||
case TOXAV_ERR_ANSWER_INVALID_BIT_RATE:
|
||||
code = OCTToxAVErrorAnswerInvalidBitRate;
|
||||
break;
|
||||
}
|
||||
|
||||
*error = [self createErrorWithCode:code description:description failureReason:failureReason];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)fillError:(NSError **)error withCErrorControl:(TOXAV_ERR_CALL_CONTROL)cError
|
||||
{
|
||||
if (! error || (cError == TOXAV_ERR_CALL_CONTROL_OK)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
OCTToxErrorCallControl code = OCTToxAVErrorControlUnknown;
|
||||
NSString *description = @"Unable set control";
|
||||
NSString *failureReason = nil;
|
||||
|
||||
switch (cError) {
|
||||
case TOXAV_ERR_CALL_CONTROL_OK:
|
||||
NSAssert(NO, @"We shouldn't be here!");
|
||||
break;
|
||||
case TOXAV_ERR_CALL_CONTROL_SYNC:
|
||||
code = OCTToxAVErrorControlSync;
|
||||
failureReason = @"Synchronization error occurred.";
|
||||
break;
|
||||
case TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND:
|
||||
code = OCTToxAVErrorControlFriendNotFound;
|
||||
failureReason = @"The friend number passed did not designate a valid friend.";
|
||||
break;
|
||||
case TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL:
|
||||
code = OCTToxAVErrorControlFriendNotInCall;
|
||||
failureReason = @"This client is currently not in a call with the friend. Before the call is answered, only CANCEL is a valid control.";
|
||||
break;
|
||||
case TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION:
|
||||
code = OCTToxAVErrorControlInvaldTransition;
|
||||
failureReason = @"Happens if user tried to pause an already paused call or if trying to resume a call that is not paused.";
|
||||
break;
|
||||
}
|
||||
|
||||
*error = [self createErrorWithCode:code description:description failureReason:failureReason];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)fillError:(NSError **)error withCErrorSetBitRate:(TOXAV_ERR_BIT_RATE_SET)cError
|
||||
{
|
||||
if (! error || (cError == TOXAV_ERR_BIT_RATE_SET_OK)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
OCTToxAVErrorSetBitRate code = OCTToxAVErrorSetBitRateUnknown;
|
||||
NSString *description = @"Unable to set audio/video bitrate";
|
||||
NSString *failureReason = nil;
|
||||
|
||||
switch (cError) {
|
||||
case TOXAV_ERR_BIT_RATE_SET_OK:
|
||||
NSAssert(NO, @"We shouldn't be here!");
|
||||
break;
|
||||
case TOXAV_ERR_BIT_RATE_SET_SYNC:
|
||||
code = OCTToxAVErrorSetBitRateSync;
|
||||
failureReason = @"Synchronization error occurred.";
|
||||
break;
|
||||
case TOXAV_ERR_BIT_RATE_SET_INVALID_BIT_RATE:
|
||||
code = OCTToxAVErrorSetBitRateInvalidBitRate;
|
||||
failureReason = @"The bit rate passed was not one of the supported values.";
|
||||
break;
|
||||
case TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_FOUND:
|
||||
code = OCTToxAVErrorSetBitRateFriendNotFound;
|
||||
failureReason = @"The friend number passed did not designate a valid friend";
|
||||
break;
|
||||
case TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_IN_CALL:
|
||||
code = OCTToxAVErrorSetBitRateFriendNotInCall;
|
||||
failureReason = @"This client is currently not in a call with the friend";
|
||||
break;
|
||||
}
|
||||
|
||||
*error = [self createErrorWithCode:code description:description failureReason:failureReason];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)fillError:(NSError **)error withCErrorSendFrame:(TOXAV_ERR_SEND_FRAME)cError
|
||||
{
|
||||
if (! error || (cError == TOXAV_ERR_SEND_FRAME_OK)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
OCTToxAVErrorSendFrame code = OCTToxAVErrorSendFrameUnknown;
|
||||
NSString *description = @"Failed to send audio/video frame";
|
||||
NSString *failureReason = @"Unable to sending audio/video frame";
|
||||
switch (cError) {
|
||||
case TOXAV_ERR_SEND_FRAME_OK:
|
||||
NSAssert(NO, @"We shouldn't be here!");
|
||||
break;
|
||||
case TOXAV_ERR_SEND_FRAME_NULL:
|
||||
code = OCTToxAVErrorSendFrameNull;
|
||||
failureReason = @"In case of video, one of Y, U, or V was NULL. In case of audio, the samples data pointer was NULL.";
|
||||
break;
|
||||
case TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND:
|
||||
code = OCTToxAVErrorSendFrameFriendNotFound;
|
||||
failureReason = @"The friend number passed did not designate a valid friend.";
|
||||
break;
|
||||
case TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL:
|
||||
code = OCTToxAVErrorSendFrameFriendNotInCall;
|
||||
failureReason = @"This client is currently not in a call with the friend";
|
||||
break;
|
||||
case TOXAV_ERR_SEND_FRAME_SYNC:
|
||||
code = OCTToxAVErrorSendFrameSync;
|
||||
failureReason = @"Synchronization error occurred";
|
||||
break;
|
||||
case TOXAV_ERR_SEND_FRAME_INVALID:
|
||||
code = OCTToxAVErrorSendFrameInvalid;
|
||||
failureReason = @"One of the frame parameters was invalid. E.g. the resolution may be too small or too large, or the audio sampling rate may be unsupported";
|
||||
break;
|
||||
case TOXAV_ERR_SEND_FRAME_PAYLOAD_TYPE_DISABLED:
|
||||
code = OCTToxAVErrorSendFramePayloadTypeDisabled;
|
||||
failureReason = @"Either friend turned off audio/video receiving or we turned off sending for the said payload.";
|
||||
break;
|
||||
case TOXAV_ERR_SEND_FRAME_RTP_FAILED:
|
||||
code = OCTToxAVErrorSendFrameRTPFailed;
|
||||
failureReason = @"Failed to push frame through rtp interface";
|
||||
break;
|
||||
}
|
||||
|
||||
*error = [self createErrorWithCode:code description:description failureReason:failureReason];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSError *)createErrorWithCode:(NSUInteger)code
|
||||
description:(NSString *)description
|
||||
failureReason:(NSString *)failureReason
|
||||
{
|
||||
NSMutableDictionary *userInfo = [NSMutableDictionary new];
|
||||
|
||||
if (description) {
|
||||
userInfo[NSLocalizedDescriptionKey] = description;
|
||||
}
|
||||
|
||||
if (failureReason) {
|
||||
userInfo[NSLocalizedFailureReasonErrorKey] = failureReason;
|
||||
}
|
||||
|
||||
return [NSError errorWithDomain:kOCTToxAVErrorDomain code:code userInfo:userInfo];
|
||||
}
|
||||
|
||||
- (void)updateTimerIntervalIfNeeded
|
||||
{
|
||||
uint64_t nextIterate = _toxav_iteration_interval(self.toxAV) * (NSEC_PER_SEC / 1000);
|
||||
|
||||
if (self.previousIterate == nextIterate) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.previousIterate = nextIterate;
|
||||
dispatch_source_set_timer(self.timer, dispatch_walltime(NULL, nextIterate), nextIterate, nextIterate / 5);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - Callbacks
|
||||
|
||||
void callIncomingCallback(ToxAV *cToxAV,
|
||||
uint32_t friendNumber,
|
||||
bool audioEnabled,
|
||||
bool videoEnabled,
|
||||
void *userData)
|
||||
{
|
||||
OCTToxAV *toxAV = (__bridge OCTToxAV *)userData;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
OCTLogCInfo(@"callIncomingCallback from friend %lu with audio:%d with video:%d", toxAV, (unsigned long)friendNumber, audioEnabled, videoEnabled);
|
||||
if ([toxAV.delegate respondsToSelector:@selector(toxAV:receiveCallAudioEnabled:videoEnabled:friendNumber:)]) {
|
||||
[toxAV.delegate toxAV:toxAV receiveCallAudioEnabled:audioEnabled videoEnabled:videoEnabled friendNumber:friendNumber];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void callStateCallback(ToxAV *cToxAV,
|
||||
uint32_t friendNumber,
|
||||
TOXAV_FRIEND_CALL_STATE cState,
|
||||
void *userData)
|
||||
{
|
||||
OCTToxAV *toxAV = (__bridge OCTToxAV *)userData;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
OCTLogCInfo(@"callStateCallback from friend %d with state: %d", toxAV, friendNumber, cState);
|
||||
|
||||
OCTToxAVCallState state = 0;
|
||||
|
||||
if (cState & TOXAV_FRIEND_CALL_STATE_ERROR) {
|
||||
state |= OCTToxAVFriendCallStateError;
|
||||
}
|
||||
if (cState & TOXAV_FRIEND_CALL_STATE_FINISHED) {
|
||||
state |= OCTToxAVFriendCallStateFinished;
|
||||
}
|
||||
if (cState & TOXAV_FRIEND_CALL_STATE_SENDING_A) {
|
||||
state |= OCTToxAVFriendCallStateSendingAudio;
|
||||
}
|
||||
if (cState & TOXAV_FRIEND_CALL_STATE_SENDING_V) {
|
||||
state |= OCTToxAVFriendCallStateSendingVideo;
|
||||
}
|
||||
if (cState & TOXAV_FRIEND_CALL_STATE_ACCEPTING_A) {
|
||||
state |= OCTToxAVFriendCallStateAcceptingAudio;
|
||||
}
|
||||
if (cState & TOXAV_FRIEND_CALL_STATE_ACCEPTING_V) {
|
||||
state |= OCTToxAVFriendCallStateAcceptingVideo;
|
||||
}
|
||||
|
||||
if ([toxAV.delegate respondsToSelector:@selector(toxAV:callStateChanged:friendNumber:)]) {
|
||||
[toxAV.delegate toxAV:toxAV callStateChanged:state friendNumber:friendNumber];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void audioBitRateStatusCallback(ToxAV *cToxAV,
|
||||
uint32_t friendNumber,
|
||||
uint32_t bit_rate,
|
||||
void *userData)
|
||||
{
|
||||
OCTToxAV *toxAV = (__bridge OCTToxAV *)userData;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
OCTLogCInfo(@"audioBitRateStatusCallback from friend %d bitRate: %d", toxAV, friendNumber, bit_rate);
|
||||
if ([toxAV.delegate respondsToSelector:@selector(toxAV:audioBitRateStatus:forFriendNumber:)]) {
|
||||
[toxAV.delegate toxAV:toxAV audioBitRateStatus:bit_rate forFriendNumber:friendNumber];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void videoBitRateStatusCallback(ToxAV *cToxAV,
|
||||
uint32_t friendNumber,
|
||||
uint32_t bit_rate,
|
||||
void *userData)
|
||||
{
|
||||
OCTToxAV *toxAV = (__bridge OCTToxAV *)userData;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
OCTLogCInfo(@"videoBitRateStatusCallback from friend %d bitRate: %d", toxAV, friendNumber, bit_rate);
|
||||
if ([toxAV.delegate respondsToSelector:@selector(toxAV:videoBitRateStatus:forFriendNumber:)]) {
|
||||
[toxAV.delegate toxAV:toxAV videoBitRateStatus:bit_rate forFriendNumber:friendNumber];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void receiveAudioFrameCallback(ToxAV *cToxAV,
|
||||
uint32_t friendNumber,
|
||||
OCTToxAVPCMData *pcm,
|
||||
OCTToxAVSampleCount sampleCount,
|
||||
OCTToxAVChannels channels,
|
||||
OCTToxAVSampleRate sampleRate,
|
||||
void *userData)
|
||||
{
|
||||
OCTToxAV *toxAV = (__bridge OCTToxAV *)userData;
|
||||
|
||||
// TOXAUDIO: -incoming-audio-
|
||||
if ([toxAV.delegate respondsToSelector:@selector(toxAV:receiveAudio:sampleCount:channels:sampleRate:friendNumber:)]) {
|
||||
[toxAV.delegate toxAV:toxAV receiveAudio:pcm sampleCount:sampleCount channels:channels sampleRate:sampleRate friendNumber:friendNumber];
|
||||
}
|
||||
}
|
||||
|
||||
void receiveVideoFrameCallback(ToxAV *cToxAV,
|
||||
uint32_t friendNumber,
|
||||
OCTToxAVVideoWidth width,
|
||||
OCTToxAVVideoHeight height,
|
||||
OCTToxAVPlaneData *yPlane, OCTToxAVPlaneData *uPlane, OCTToxAVPlaneData *vPlane,
|
||||
OCTToxAVStrideData yStride, OCTToxAVStrideData uStride, OCTToxAVStrideData vStride,
|
||||
void *userData)
|
||||
{
|
||||
OCTToxAV *toxAV = (__bridge OCTToxAV *)userData;
|
||||
|
||||
if ([toxAV.delegate respondsToSelector:@selector(toxAV:receiveVideoFrameWithWidth:height:yPlane:uPlane:vPlane:yStride:uStride:vStride:friendNumber:)]) {
|
||||
[toxAV.delegate toxAV:toxAV
|
||||
receiveVideoFrameWithWidth:width height:height
|
||||
yPlane:yPlane uPlane:uPlane vPlane:vPlane
|
||||
yStride:yStride uStride:uStride vStride:vStride
|
||||
friendNumber:friendNumber];
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTToxAVConstants.h"
|
||||
|
||||
const OCTToxAVVideoBitRate kOCTToxAVVideoBitRateDisable = 0;
|
||||
|
||||
NSString *const kOCTToxAVErrorDomain = @"me.dvor.objcTox.ErrorDomain";
|
@ -0,0 +1,25 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTToxConstants.h"
|
||||
#import <toxcore/tox.h>
|
||||
|
||||
const OCTToxFriendNumber kOCTToxFriendNumberFailure = UINT32_MAX;
|
||||
const OCTToxFileNumber kOCTToxFileNumberFailure = UINT32_MAX;
|
||||
const OCTToxFileSize kOCTToxFileSizeUnknown = UINT64_MAX;
|
||||
|
||||
NSString *const kOCTToxErrorDomain = @"me.dvor.objcTox.OCTToxErrorDomain";
|
||||
|
||||
const NSUInteger kOCTToxAddressLength = 2 * TOX_ADDRESS_SIZE;
|
||||
const NSUInteger kOCTToxPublicKeyLength = 2 * TOX_PUBLIC_KEY_SIZE;
|
||||
const NSUInteger kOCTToxSecretKeyLength = 2 * TOX_SECRET_KEY_SIZE;
|
||||
const NSUInteger kOCTToxMaxNameLength = TOX_MAX_NAME_LENGTH;
|
||||
const NSUInteger kOCTToxMaxStatusMessageLength = TOX_MAX_STATUS_MESSAGE_LENGTH;
|
||||
const NSUInteger kOCTToxMaxFriendRequestLength = TOX_MAX_FRIEND_REQUEST_LENGTH;
|
||||
const NSUInteger kOCTToxMaxMessageLength = TOX_MAX_MESSAGE_LENGTH;
|
||||
const NSUInteger kOCTToxMaxCustomPacketSize = TOX_MAX_CUSTOM_PACKET_SIZE;
|
||||
const NSUInteger kOCTToxMaxFileNameLength = TOX_MAX_FILENAME_LENGTH;
|
||||
|
||||
const NSUInteger kOCTToxHashLength = TOX_HASH_LENGTH;
|
||||
const NSUInteger kOCTToxFileIdLength = TOX_FILE_ID_LENGTH;
|
@ -0,0 +1,272 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTToxEncryptSave.h"
|
||||
#import <toxcore/toxencryptsave/toxencryptsave.h>
|
||||
#import "OCTToxEncryptSaveConstants.h"
|
||||
#import "OCTTox+Private.h"
|
||||
|
||||
@interface OCTToxEncryptSave ()
|
||||
|
||||
@property (assign, nonatomic) Tox_Pass_Key *passKey;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTToxEncryptSave
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (nullable instancetype)initWithPassphrase:(nonnull NSString *)passphrase
|
||||
toxData:(nullable NSData *)toxData
|
||||
error:(NSError *__nullable *__nullable)error
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (! self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
TOX_ERR_KEY_DERIVATION cError;
|
||||
|
||||
uint8_t salt[TOX_PASS_SALT_LENGTH];
|
||||
bool hasSalt = false;
|
||||
|
||||
if (toxData) {
|
||||
hasSalt = tox_get_salt(toxData.bytes, salt, NULL);
|
||||
}
|
||||
|
||||
if (hasSalt) {
|
||||
_passKey = tox_pass_key_derive_with_salt(
|
||||
(const uint8_t *)[passphrase cStringUsingEncoding:NSUTF8StringEncoding],
|
||||
[passphrase lengthOfBytesUsingEncoding:NSUTF8StringEncoding],
|
||||
salt,
|
||||
&cError);
|
||||
}
|
||||
else {
|
||||
_passKey = tox_pass_key_derive(
|
||||
(const uint8_t *)[passphrase cStringUsingEncoding:NSUTF8StringEncoding],
|
||||
[passphrase lengthOfBytesUsingEncoding:NSUTF8StringEncoding],
|
||||
&cError);
|
||||
}
|
||||
|
||||
[OCTToxEncryptSave fillError:error withCErrorKeyDerivation:cError];
|
||||
|
||||
return (_passKey != NULL) ? self : nil;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
if (_passKey) {
|
||||
tox_pass_key_free(_passKey);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Public class methods
|
||||
|
||||
+ (BOOL)isDataEncrypted:(nonnull NSData *)data
|
||||
{
|
||||
return tox_is_data_encrypted(data.bytes);
|
||||
}
|
||||
|
||||
+ (nullable NSData *)encryptData:(nonnull NSData *)data
|
||||
withPassphrase:(nonnull NSString *)passphrase
|
||||
error:(NSError *__nullable *__nullable)error
|
||||
{
|
||||
NSParameterAssert(data);
|
||||
NSParameterAssert(passphrase);
|
||||
|
||||
return [OCTToxEncryptSave convertDataOfLength:data.length encrypt:YES withConvertBlock:^bool (uint8_t *out) {
|
||||
TOX_ERR_ENCRYPTION cError;
|
||||
|
||||
bool result = tox_pass_encrypt(
|
||||
data.bytes,
|
||||
data.length,
|
||||
(const uint8_t *)[passphrase cStringUsingEncoding:NSUTF8StringEncoding],
|
||||
[passphrase lengthOfBytesUsingEncoding:NSUTF8StringEncoding],
|
||||
out,
|
||||
&cError);
|
||||
|
||||
[OCTToxEncryptSave fillError:error withCErrorEncryption:cError];
|
||||
|
||||
return result;
|
||||
}];
|
||||
}
|
||||
|
||||
+ (nullable NSData *)decryptData:(nonnull NSData *)data
|
||||
withPassphrase:(nonnull NSString *)passphrase
|
||||
error:(NSError *__nullable *__nullable)error
|
||||
{
|
||||
NSParameterAssert(data);
|
||||
NSParameterAssert(passphrase);
|
||||
|
||||
return [OCTToxEncryptSave convertDataOfLength:data.length encrypt:NO withConvertBlock:^bool (uint8_t *out) {
|
||||
TOX_ERR_DECRYPTION cError;
|
||||
|
||||
bool result = tox_pass_decrypt(
|
||||
data.bytes,
|
||||
data.length,
|
||||
(const uint8_t *)[passphrase cStringUsingEncoding:NSUTF8StringEncoding],
|
||||
[passphrase lengthOfBytesUsingEncoding:NSUTF8StringEncoding],
|
||||
out,
|
||||
&cError);
|
||||
|
||||
[OCTToxEncryptSave fillError:error withCErrorDecryption:cError];
|
||||
|
||||
return result;
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Public instance method
|
||||
|
||||
- (nullable NSData *)encryptData:(nonnull NSData *)data error:(NSError *__nullable *__nullable)error
|
||||
{
|
||||
NSParameterAssert(data);
|
||||
|
||||
return [OCTToxEncryptSave convertDataOfLength:data.length encrypt:YES withConvertBlock:^bool (uint8_t *out) {
|
||||
TOX_ERR_ENCRYPTION cError;
|
||||
|
||||
bool result = tox_pass_key_encrypt(
|
||||
self.passKey,
|
||||
data.bytes,
|
||||
data.length,
|
||||
out,
|
||||
&cError);
|
||||
|
||||
[OCTToxEncryptSave fillError:error withCErrorEncryption:cError];
|
||||
|
||||
return result;
|
||||
}];
|
||||
}
|
||||
|
||||
- (nullable NSData *)decryptData:(nonnull NSData *)data error:(NSError *__nullable *__nullable)error
|
||||
{
|
||||
NSParameterAssert(data);
|
||||
|
||||
return [OCTToxEncryptSave convertDataOfLength:data.length encrypt:NO withConvertBlock:^bool (uint8_t *out) {
|
||||
TOX_ERR_DECRYPTION cError;
|
||||
|
||||
bool result = tox_pass_key_decrypt(
|
||||
self.passKey,
|
||||
data.bytes,
|
||||
data.length,
|
||||
out,
|
||||
&cError);
|
||||
|
||||
[OCTToxEncryptSave fillError:error withCErrorDecryption:cError];
|
||||
|
||||
return result;
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
+ (NSData *)convertDataOfLength:(NSUInteger)dataLength
|
||||
encrypt:(BOOL)encrypt
|
||||
withConvertBlock:(bool (^)(uint8_t *out))convertBlock
|
||||
{
|
||||
NSUInteger outLength = dataLength + (encrypt ? TOX_PASS_ENCRYPTION_EXTRA_LENGTH : -TOX_PASS_ENCRYPTION_EXTRA_LENGTH);
|
||||
uint8_t *out = malloc(outLength);
|
||||
|
||||
bool result = convertBlock(out);
|
||||
NSData *resultData = nil;
|
||||
|
||||
if (result) {
|
||||
resultData = [NSData dataWithBytes:out length:outLength];
|
||||
}
|
||||
|
||||
if (out) {
|
||||
free(out);
|
||||
}
|
||||
|
||||
return resultData;
|
||||
}
|
||||
|
||||
+ (BOOL)fillError:(NSError **)error withCErrorKeyDerivation:(TOX_ERR_KEY_DERIVATION)cError
|
||||
{
|
||||
if (! error || (cError == TOX_ERR_KEY_DERIVATION_OK)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
switch (cError) {
|
||||
case TOX_ERR_KEY_DERIVATION_OK:
|
||||
NSAssert(NO, @"We shouldn't be here");
|
||||
return NO;
|
||||
case TOX_ERR_KEY_DERIVATION_NULL:
|
||||
case TOX_ERR_KEY_DERIVATION_FAILED:
|
||||
*error = [OCTTox createErrorWithCode:OCTToxEncryptSaveKeyDerivationErrorFailed
|
||||
description:@"Cannot create key from given passphrase"
|
||||
failureReason:nil];
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)fillError:(NSError **)error withCErrorEncryption:(TOX_ERR_ENCRYPTION)cError
|
||||
{
|
||||
if (! error || (cError == TOX_ERR_ENCRYPTION_OK)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
OCTToxEncryptSaveEncryptionError code;
|
||||
NSString *description = @"Encryption failed";
|
||||
NSString *failureReason = nil;
|
||||
|
||||
switch (cError) {
|
||||
case TOX_ERR_ENCRYPTION_OK:
|
||||
NSAssert(NO, @"We shouldn't be here");
|
||||
return NO;
|
||||
case TOX_ERR_ENCRYPTION_NULL:
|
||||
code = OCTToxEncryptSaveEncryptionErrorNull;
|
||||
failureReason = @"Some input data was empty.";
|
||||
break;
|
||||
case TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED:
|
||||
case TOX_ERR_ENCRYPTION_FAILED:
|
||||
code = OCTToxEncryptSaveEncryptionErrorFailed;
|
||||
failureReason = @"Encryption failed, please report";
|
||||
break;
|
||||
}
|
||||
|
||||
*error = [OCTTox createErrorWithCode:code description:description failureReason:failureReason];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)fillError:(NSError **)error withCErrorDecryption:(TOX_ERR_DECRYPTION)cError
|
||||
{
|
||||
if (! error || (cError == TOX_ERR_DECRYPTION_OK)) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
OCTToxEncryptSaveDecryptionError code;
|
||||
NSString *description = @"Decryption failed";
|
||||
NSString *failureReason = nil;
|
||||
|
||||
switch (cError) {
|
||||
case TOX_ERR_DECRYPTION_OK:
|
||||
NSAssert(NO, @"We shouldn't be here");
|
||||
return NO;
|
||||
case TOX_ERR_DECRYPTION_NULL:
|
||||
code = OCTToxEncryptSaveDecryptionErrorNull;
|
||||
failureReason = @"Some input data was empty.";
|
||||
break;
|
||||
case TOX_ERR_DECRYPTION_BAD_FORMAT:
|
||||
code = OCTToxEncryptSaveDecryptionErrorBadFormat;
|
||||
failureReason = @"The input data has bad format";
|
||||
break;
|
||||
case TOX_ERR_DECRYPTION_INVALID_LENGTH:
|
||||
case TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED:
|
||||
case TOX_ERR_DECRYPTION_FAILED:
|
||||
code = OCTToxEncryptSaveDecryptionErrorFailed;
|
||||
failureReason = @"Decryption failed, passphrase is incorrect or data is corrupt";
|
||||
break;
|
||||
}
|
||||
|
||||
*error = [OCTTox createErrorWithCode:code description:description failureReason:failureReason];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
@ -0,0 +1,11 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTToxOptions.h"
|
||||
|
||||
@interface OCTToxOptions (Private)
|
||||
|
||||
@property (nonatomic, assign, readonly) struct Tox_Options *options;
|
||||
|
||||
@end
|
212
local_pod_repo/objcTox/Classes/Private/Wrapper/OCTToxOptions.m
Normal file
212
local_pod_repo/objcTox/Classes/Private/Wrapper/OCTToxOptions.m
Normal file
@ -0,0 +1,212 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#import "OCTToxOptions+Private.h"
|
||||
#import <toxcore/tox.h>
|
||||
|
||||
@interface OCTToxOptions ()
|
||||
|
||||
@property (nonatomic, assign, readonly) struct Tox_Options *options;
|
||||
|
||||
// Used to retain proxy_host option.
|
||||
@property (nonatomic, copy) NSString *proxyHostStorage;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OCTToxOptions
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (! self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_options = tox_options_new(NULL);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
tox_options_free(_options);
|
||||
}
|
||||
|
||||
#pragma mark - Description
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"OCTToxOptions:\n"
|
||||
@"ipv6Enabled %d\n"
|
||||
@"udpEnabled %d\n"
|
||||
@"localDiscoveryEnabled %d\n"
|
||||
@"proxyType %lu\n"
|
||||
@"proxyHost %@\n"
|
||||
@"proxyPort %d\n"
|
||||
@"startPort %d\n"
|
||||
@"endPort %d\n"
|
||||
@"tcpPort %d\n"
|
||||
@"holePunchingEnabled %d\n",
|
||||
self.ipv6Enabled,
|
||||
self.udpEnabled,
|
||||
self.localDiscoveryEnabled,
|
||||
self.proxyType,
|
||||
self.proxyHost,
|
||||
self.proxyPort,
|
||||
self.startPort,
|
||||
self.endPort,
|
||||
self.tcpPort,
|
||||
self.holePunchingEnabled];
|
||||
}
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (BOOL)ipv6Enabled
|
||||
{
|
||||
return tox_options_get_ipv6_enabled(self.options);
|
||||
}
|
||||
|
||||
- (void)setIpv6Enabled:(BOOL)enabled
|
||||
{
|
||||
tox_options_set_ipv6_enabled(self.options, enabled);
|
||||
}
|
||||
|
||||
- (BOOL)udpEnabled
|
||||
{
|
||||
return tox_options_get_udp_enabled(self.options);
|
||||
}
|
||||
|
||||
- (void)setUdpEnabled:(BOOL)enabled
|
||||
{
|
||||
tox_options_set_udp_enabled(self.options, enabled);
|
||||
}
|
||||
|
||||
- (BOOL)localDiscoveryEnabled
|
||||
{
|
||||
return tox_options_get_local_discovery_enabled(self.options);
|
||||
}
|
||||
|
||||
- (void)setLocalDiscoveryEnabled:(BOOL)enabled
|
||||
{
|
||||
tox_options_set_local_discovery_enabled(self.options, enabled);
|
||||
}
|
||||
|
||||
- (OCTToxProxyType)proxyType
|
||||
{
|
||||
switch (tox_options_get_proxy_type(self.options)) {
|
||||
case TOX_PROXY_TYPE_NONE:
|
||||
return OCTToxProxyTypeNone;
|
||||
case TOX_PROXY_TYPE_HTTP:
|
||||
return OCTToxProxyTypeHTTP;
|
||||
case TOX_PROXY_TYPE_SOCKS5:
|
||||
return OCTToxProxyTypeSocks5;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setProxyType:(OCTToxProxyType)type
|
||||
{
|
||||
switch (type) {
|
||||
case OCTToxProxyTypeNone:
|
||||
tox_options_set_proxy_type(self.options, TOX_PROXY_TYPE_NONE);
|
||||
break;
|
||||
case OCTToxProxyTypeHTTP:
|
||||
tox_options_set_proxy_type(self.options, TOX_PROXY_TYPE_HTTP);
|
||||
break;
|
||||
case OCTToxProxyTypeSocks5:
|
||||
tox_options_set_proxy_type(self.options, TOX_PROXY_TYPE_SOCKS5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)proxyHost
|
||||
{
|
||||
const char *cHost = tox_options_get_proxy_host(self.options);
|
||||
|
||||
if (cHost) {
|
||||
return [NSString stringWithCString:cHost encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)setProxyHost:(NSString *)host
|
||||
{
|
||||
self.proxyHostStorage = host;
|
||||
tox_options_set_proxy_host(self.options, self.proxyHostStorage.UTF8String);
|
||||
}
|
||||
|
||||
- (uint16_t)proxyPort
|
||||
{
|
||||
return tox_options_get_proxy_port(self.options);
|
||||
}
|
||||
|
||||
- (void)setProxyPort:(uint16_t)port
|
||||
{
|
||||
tox_options_set_proxy_port(self.options, port);
|
||||
}
|
||||
|
||||
- (uint16_t)startPort
|
||||
{
|
||||
return tox_options_get_start_port(self.options);
|
||||
}
|
||||
|
||||
- (void)setStartPort:(uint16_t)port
|
||||
{
|
||||
tox_options_set_start_port(self.options, port);
|
||||
}
|
||||
|
||||
- (uint16_t)endPort
|
||||
{
|
||||
return tox_options_get_end_port(self.options);
|
||||
}
|
||||
|
||||
- (void)setEndPort:(uint16_t)port
|
||||
{
|
||||
tox_options_set_end_port(self.options, port);
|
||||
}
|
||||
|
||||
- (uint16_t)tcpPort
|
||||
{
|
||||
return tox_options_get_tcp_port(self.options);
|
||||
}
|
||||
|
||||
- (void)setTcpPort:(uint16_t)port
|
||||
{
|
||||
tox_options_set_tcp_port(self.options, port);
|
||||
}
|
||||
|
||||
- (BOOL)holePunchingEnabled
|
||||
{
|
||||
return tox_options_get_hole_punching_enabled(self.options);
|
||||
}
|
||||
|
||||
- (void)setHolePunchingEnabled:(BOOL)enabled
|
||||
{
|
||||
tox_options_set_hole_punching_enabled(self.options, enabled);
|
||||
}
|
||||
|
||||
#pragma mark - NSCopying
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
OCTToxOptions *options = [[[self class] allocWithZone:zone] init];
|
||||
|
||||
options.ipv6Enabled = self.ipv6Enabled;
|
||||
options.udpEnabled = self.udpEnabled;
|
||||
options.localDiscoveryEnabled = self.localDiscoveryEnabled;
|
||||
options.proxyType = self.proxyType;
|
||||
options.proxyHost = self.proxyHost;
|
||||
options.proxyPort = self.proxyPort;
|
||||
options.startPort = self.startPort;
|
||||
options.endPort = self.endPort;
|
||||
options.tcpPort = self.tcpPort;
|
||||
options.holePunchingEnabled = self.holePunchingEnabled;
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@end
|
Reference in New Issue
Block a user