mirror of
https://github.com/transmission/transmission.git
synced 2025-12-24 12:28:52 +00:00
add the beginnings of ipc to the mac front end
This commit is contained in:
@@ -1430,8 +1430,10 @@
|
||||
GCC_WARN_UNUSED_VARIABLE = NO;
|
||||
MACOSX_DEPLOYMENT_TARGET_i386 = 10.4;
|
||||
MACOSX_DEPLOYMENT_TARGET_ppc = 10.4;
|
||||
OTHER_CFLAGS = "$(inherited)";
|
||||
PREBINDING = NO;
|
||||
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
|
||||
ZERO_LINK = NO;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
||||
@@ -76,26 +76,26 @@ pushdir( char * path, const char * file, size_t size )
|
||||
void
|
||||
confpath( char * buf, size_t len, const char * file, enum confpathtype type )
|
||||
{
|
||||
const char * typestr;
|
||||
strlcpy( buf, tr_getPrefsDirectory(), len );
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case CONF_PATH_TYPE_DAEMON:
|
||||
typestr = "daemon";
|
||||
pushdir( buf, "daemon", len );
|
||||
break;
|
||||
case CONF_PATH_TYPE_GTK:
|
||||
typestr = "gtk";
|
||||
pushdir( buf, "gtk", len );
|
||||
break;
|
||||
case CONF_PATH_TYPE_OSX:
|
||||
break;
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
strlcpy( buf, tr_getPrefsDirectory(), len );
|
||||
pushdir( buf, typestr, len );
|
||||
if( NULL != file )
|
||||
{
|
||||
pushdir( buf, file, len );
|
||||
pushdir( buf, file, len );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ enum confpathtype
|
||||
{
|
||||
CONF_PATH_TYPE_DAEMON,
|
||||
CONF_PATH_TYPE_GTK,
|
||||
CONF_PATH_TYPE_OSX,
|
||||
};
|
||||
|
||||
struct bufferevent;
|
||||
|
||||
@@ -132,7 +132,8 @@ usage( const char * msg, ... )
|
||||
"\n"
|
||||
" -h --help Display this message and exit\n"
|
||||
" -t --type daemon Use the daemon frontend, transmission-daemon\n"
|
||||
" -t --type gtk Use the GTK+ frontend, transmission-gtk\n",
|
||||
" -t --type gtk Use the GTK+ frontend, transmission-gtk\n"
|
||||
" -t --type mac Use the Mac OS X frontend\n",
|
||||
getmyname(), VERSION_STRING, VERSION_REVISION );
|
||||
exit( EXIT_SUCCESS );
|
||||
}
|
||||
@@ -168,6 +169,14 @@ readargs( int argc, char ** argv, char ** sockpath )
|
||||
type = CONF_PATH_TYPE_GTK;
|
||||
*sockpath = NULL;
|
||||
}
|
||||
else if( 0 == strcasecmp( "mac", optarg ) ||
|
||||
0 == strcasecmp( "osx", optarg ) ||
|
||||
0 == strcasecmp( "macos", optarg ) ||
|
||||
0 == strcasecmp( "macosx", optarg ) )
|
||||
{
|
||||
type = CONF_PATH_TYPE_OSX;
|
||||
*sockpath = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*sockpath = optarg;
|
||||
|
||||
@@ -248,6 +248,7 @@ usage( const char * msg, ... )
|
||||
" -S --stop all Stop all running torrents\n"
|
||||
" -t --type daemon Use the daemon frontend, transmission-daemon\n"
|
||||
" -t --type gtk Use the GTK+ frontend, transmission-gtk\n"
|
||||
" -t --type mac Use the MacOS X frontend\n"
|
||||
" -u --upload-limit <int> Max upload rate in KiB/s\n"
|
||||
" -U --upload-unlimited No upload rate limit\n"
|
||||
" -x --proxy Use proxy command to connect to frontend\n",
|
||||
@@ -373,6 +374,14 @@ readargs( int argc, char ** argv, struct opts * opts )
|
||||
opts->type = CONF_PATH_TYPE_GTK;
|
||||
opts->sock = NULL;
|
||||
}
|
||||
else if( 0 == strcasecmp( "mac", optarg ) ||
|
||||
0 == strcasecmp( "osx", optarg ) ||
|
||||
0 == strcasecmp( "macos", optarg ) ||
|
||||
0 == strcasecmp( "macosx", optarg ) )
|
||||
{
|
||||
opts->type = CONF_PATH_TYPE_OSX;
|
||||
opts->sock = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
opts->sock = optarg;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#import "Badger.h"
|
||||
#import "ImageBackgroundView.h"
|
||||
#import "FilterBarButton.h"
|
||||
#import "IPCController.h"
|
||||
|
||||
#import <Growl/Growl.h>
|
||||
|
||||
@@ -49,6 +50,7 @@
|
||||
NSUserDefaults * fDefaults;
|
||||
InfoWindowController * fInfoController;
|
||||
MessageWindowController * fMessageController;
|
||||
IPCController * fIPCController;
|
||||
|
||||
IBOutlet NSWindow * fWindow;
|
||||
DragOverlayWindow * fOverlayWindow;
|
||||
@@ -97,6 +99,8 @@
|
||||
NSMutableArray * fAutoImportedNames;
|
||||
NSMutableDictionary * fPendingTorrentDownloads;
|
||||
NSTimer * fAutoImportTimer;
|
||||
|
||||
BOOL fRemoteQuit;
|
||||
}
|
||||
|
||||
- (void) openFiles: (NSArray *) filenames;
|
||||
|
||||
@@ -168,6 +168,8 @@ static void sleepCallBack(void * controller, io_service_t y, natural_t messageTy
|
||||
|
||||
fBadger = [[Badger alloc] initWithLib: fLib];
|
||||
fOverlayWindow = [[DragOverlayWindow alloc] initWithLib: fLib];
|
||||
fIPCController = [[IPCController alloc] init];
|
||||
[fIPCController setDelegate: self];
|
||||
|
||||
[GrowlApplicationBridge setGrowlDelegate: self];
|
||||
|
||||
@@ -189,6 +191,7 @@ static void sleepCallBack(void * controller, io_service_t y, natural_t messageTy
|
||||
[fDisplayedTorrents release];
|
||||
[fBadger release];
|
||||
[fOverlayWindow release];
|
||||
[fIPCController release];
|
||||
|
||||
[fAutoImportedNames release];
|
||||
[fPendingTorrentDownloads release];
|
||||
@@ -456,7 +459,7 @@ static void sleepCallBack(void * controller, io_service_t y, natural_t messageTy
|
||||
|
||||
- (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *) sender
|
||||
{
|
||||
if (!fUpdateInProgress && [fDefaults boolForKey: @"CheckQuit"])
|
||||
if (!fUpdateInProgress && !fRemoteQuit && [fDefaults boolForKey: @"CheckQuit"])
|
||||
{
|
||||
int active = 0, downloading = 0;
|
||||
Torrent * torrent;
|
||||
@@ -2979,4 +2982,148 @@ static void sleepCallBack(void * controller, io_service_t y, natural_t messageTy
|
||||
stringByAppendingPathComponent: [[NSProcessInfo processInfo] processName]];
|
||||
}
|
||||
|
||||
- (void) ipcQuit
|
||||
{
|
||||
fRemoteQuit = YES;
|
||||
[NSApp terminate: self];
|
||||
}
|
||||
|
||||
- (NSArray *) ipcGetTorrentsByID: (NSArray *) idlist
|
||||
{
|
||||
NSEnumerator * torenum, * idenum;
|
||||
Torrent * tor;
|
||||
NSNumber * num;
|
||||
NSMutableArray * ret;
|
||||
|
||||
if (!idlist)
|
||||
{
|
||||
return fTorrents;
|
||||
}
|
||||
|
||||
ret = [NSMutableArray array];
|
||||
torenum = [fTorrents objectEnumerator];
|
||||
while ((tor = [torenum nextObject]))
|
||||
{
|
||||
idenum = [idlist objectEnumerator];
|
||||
while ((num = [idenum nextObject]))
|
||||
{
|
||||
if ([num intValue] == [tor getID])
|
||||
{
|
||||
[ret addObject: tor];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (NSArray *) ipcGetTorrentsByHash: (NSArray *) hashlist
|
||||
{
|
||||
NSEnumerator * torenum, * hashenum;
|
||||
Torrent * tor;
|
||||
NSString * torhash, * listhash;
|
||||
NSMutableArray * ret;
|
||||
|
||||
if (!hashlist)
|
||||
return fTorrents;
|
||||
|
||||
ret = [NSMutableArray array];
|
||||
torenum = [fTorrents objectEnumerator];
|
||||
while ((tor = [torenum nextObject]))
|
||||
{
|
||||
torhash = [tor hashString];
|
||||
hashenum = [hashlist objectEnumerator];
|
||||
while ((listhash = [hashenum nextObject]))
|
||||
{
|
||||
if (NSOrderedSame == [torhash caseInsensitiveCompare: listhash])
|
||||
{
|
||||
[ret addObject: tor];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (BOOL) ipcAddTorrents: (NSArray *) torrents
|
||||
{
|
||||
/* 'torrents' is NSArray of NSString torrent file paths, should
|
||||
return NO if torrent fails to load */
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) ipcAddTorrentFile: (NSString *) path
|
||||
directory: (NSString *) dir
|
||||
{
|
||||
/* 'path' is path to torrent file, 'dir' is the directory it
|
||||
should download it's files to and may be nil, should return NO
|
||||
if torrent fails to load */
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) ipcAddTorrentFileAutostart: (NSString *) path
|
||||
directory: (NSString *) dir
|
||||
autostart: (BOOL) autostart
|
||||
{
|
||||
/* 'path' is path to torrent file, 'dir' is the directory it
|
||||
should download it's files to and may be nil, 'autostart' is a
|
||||
boolean indicating if the torrent should be automatically
|
||||
started (or queued to start, I guess), should return NO if
|
||||
torrent fails to load */
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) ipcAddTorrentData: (NSData *) data
|
||||
directory: (NSString *) dir
|
||||
{
|
||||
/* 'data' is the contents of a torrent file, 'dir' is the
|
||||
directory it should download it's files to and may be nil,
|
||||
should return NO if torrent fails to load */
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) ipcAddTorrentDataAutostart: (NSData *) path
|
||||
directory: (NSString *) dir
|
||||
autostart: (BOOL) autostart
|
||||
{
|
||||
/* 'data' is the contents of a torrent file, 'dir' is the
|
||||
directory it should download it's files to and may be nil,
|
||||
'autostart' is a boolean indicating if the torrent should be
|
||||
automatically started (or queued to start, I guess), should
|
||||
return NO if torrent fails to load */
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) ipcStartTorrents: (NSArray *) torrents
|
||||
{
|
||||
if (!torrents)
|
||||
[self resumeAllTorrents: self];
|
||||
else
|
||||
[self resumeTorrents: torrents];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) ipcStopTorrents: (NSArray *) torrents
|
||||
{
|
||||
if (!torrents)
|
||||
[self stopAllTorrents: self];
|
||||
else
|
||||
[self stopTorrents: torrents];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) ipcRemoveTorrents: (NSArray *) torrents
|
||||
{
|
||||
if (!torrents)
|
||||
torrents = [NSArray arrayWithArray: fTorrents];
|
||||
|
||||
[self confirmRemoveTorrents: torrents deleteData: NO deleteTorrent: NO];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
70
macosx/IPCController.h
Normal file
70
macosx/IPCController.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/******************************************************************************
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (c) 2007 Transmission authors and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef IPCCONTROLLER_H
|
||||
#define IPCCONTROLLER_H
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "ipcparse.h"
|
||||
|
||||
@interface NSObject (IPCControllerDelegate)
|
||||
|
||||
- (void) ipcQuit;
|
||||
- (NSArray *) ipcGetTorrentsByID: (NSArray *) idlist;
|
||||
- (NSArray *) ipcGetTorrentsByHash: (NSArray *) hashlist;
|
||||
- (BOOL) ipcAddTorrents: (NSArray *) torrents;
|
||||
- (BOOL) ipcAddTorrentFile: (NSString *) path
|
||||
directory: (NSString *) dir;
|
||||
- (BOOL) ipcAddTorrentFileAutostart: (NSString *) path
|
||||
directory: (NSString *) dir
|
||||
autostart: (BOOL) autostart;
|
||||
- (BOOL) ipcAddTorrentData: (NSData *) data
|
||||
directory: (NSString *) dir;
|
||||
- (BOOL) ipcAddTorrentDataAutostart: (NSData *) data
|
||||
directory: (NSString *) dir
|
||||
autostart: (BOOL) autostart;
|
||||
- (BOOL) ipcStartTorrents: (NSArray *) torrents;
|
||||
- (BOOL) ipcStopTorrents: (NSArray *) torrents;
|
||||
- (BOOL) ipcRemoveTorrents: (NSArray *) torrents;
|
||||
/* XXX how to get and set prefs nicely? */
|
||||
|
||||
@end
|
||||
|
||||
@interface IPCController : NSObject
|
||||
{
|
||||
NSSocketPort * _sock;
|
||||
NSFileHandle * _listen;
|
||||
struct ipc_funcs * _funcs;
|
||||
NSMutableArray * _clients;
|
||||
id _delegate;
|
||||
}
|
||||
|
||||
- (id) init;
|
||||
- (id) delegate;
|
||||
- (void) setDelegate: (id) newdelegate;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
912
macosx/IPCController.m
Normal file
912
macosx/IPCController.m
Normal file
@@ -0,0 +1,912 @@
|
||||
/******************************************************************************
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (c) 2007 Transmission authors and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "bencode.h"
|
||||
#include "ipcparse.h"
|
||||
#include "transmission.h"
|
||||
|
||||
#import "IPCController.h"
|
||||
#import "Torrent.h"
|
||||
|
||||
static void
|
||||
getaddr( struct sockaddr_un * );
|
||||
static NSArray *
|
||||
bencarray( benc_val_t * val, int type );
|
||||
static void
|
||||
msg_lookup ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg );
|
||||
static void
|
||||
msg_info ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg );
|
||||
void
|
||||
msg_infoall ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg );
|
||||
void
|
||||
msg_action ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg );
|
||||
void
|
||||
msg_actionall( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg );
|
||||
void
|
||||
msg_addold ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg );
|
||||
void
|
||||
msg_addnew ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg );
|
||||
void
|
||||
msg_getbool ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg );
|
||||
void
|
||||
msg_getint ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg );
|
||||
void
|
||||
msg_getstr ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg );
|
||||
void
|
||||
msg_setbool ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg );
|
||||
void
|
||||
msg_setint ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg );
|
||||
void
|
||||
msg_setstr ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg );
|
||||
static void
|
||||
msg_default ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg );
|
||||
|
||||
@interface IPCClient : NSObject
|
||||
{
|
||||
NSFileHandle * _handle;
|
||||
struct ipc_info _ipc;
|
||||
IPCController * _controller;
|
||||
NSMutableData * _buf;
|
||||
}
|
||||
|
||||
- (id) initClient: (IPCController *) controller
|
||||
funcs: (struct ipc_funcs *) funcs
|
||||
handle: (NSFileHandle *) handle;
|
||||
- (IPCController *) controller;
|
||||
- (struct ipc_info *) ipc;
|
||||
- (void) gotdata: (NSNotification *) notification;
|
||||
- (BOOL) sendresp: (uint8_t *) buf
|
||||
size: (size_t) size;
|
||||
- (BOOL) sendrespEmpty: (enum ipc_msg) msgid
|
||||
tag: (int64_t) tag;
|
||||
- (BOOL) sendrespInt: (enum ipc_msg) msgid
|
||||
tag: (int64_t) tag
|
||||
val: (int64_t) val;
|
||||
- (BOOL) sendrespStr: (enum ipc_msg) msgid
|
||||
tag: (int64_t) tag
|
||||
val: (NSString *) val;
|
||||
- (void) sendrespInfo: (enum ipc_msg) respid
|
||||
tag: (int64_t) tag
|
||||
torrents: (NSArray *) tors
|
||||
types: (int) types;
|
||||
|
||||
@end
|
||||
|
||||
@interface IPCController (Private)
|
||||
|
||||
- (void) newclient: (NSNotification *) notification;
|
||||
- (void) killclient: (IPCClient *) client;
|
||||
|
||||
@end
|
||||
|
||||
@implementation IPCController
|
||||
|
||||
- (id) init
|
||||
{
|
||||
struct sockaddr_un sun;
|
||||
|
||||
self = [super init];
|
||||
if( nil == self )
|
||||
return nil;
|
||||
|
||||
getaddr( &sun );
|
||||
unlink( sun.sun_path );
|
||||
_sock = [[NSSocketPort alloc]
|
||||
initWithProtocolFamily: PF_UNIX
|
||||
socketType: SOCK_STREAM
|
||||
protocol: 0
|
||||
address: [NSData dataWithBytes: &sun
|
||||
length: sizeof(sun)]];
|
||||
_listen = [[NSFileHandle alloc]
|
||||
initWithFileDescriptor: [_sock socket]
|
||||
closeOnDealloc: YES];
|
||||
_funcs = ipc_initmsgs();
|
||||
_clients = [[NSMutableArray alloc] init];
|
||||
|
||||
/* XXX is this error checking bogus? */
|
||||
if( nil == _sock ||
|
||||
nil == _listen ||
|
||||
NULL == _funcs ||
|
||||
nil == _clients ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_ADDMANYFILES, msg_addold ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_ADDONEFILE, msg_addnew ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_AUTOMAP, msg_setbool ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_AUTOSTART, msg_setbool ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_DIR, msg_setstr ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_DOWNLIMIT, msg_setint ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_GETAUTOMAP, msg_getbool ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_GETAUTOSTART, msg_getbool ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_GETDIR, msg_getstr ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_GETDOWNLIMIT, msg_getint ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_GETINFO, msg_info ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_GETINFOALL, msg_infoall ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_GETPEX, msg_getbool ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_GETPORT, msg_getint ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_GETSTAT, msg_info ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_GETSTATALL, msg_infoall ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_GETUPLIMIT, msg_getint ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_LOOKUP, msg_lookup ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_PEX, msg_setbool ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_PORT, msg_setint ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_REMOVE, msg_action ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_REMOVEALL, msg_actionall ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_START, msg_action ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_STARTALL, msg_actionall ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_STOP, msg_action ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_STOPALL, msg_actionall ) ||
|
||||
0 > ipc_addmsg( _funcs, IPC_MSG_UPLIMIT, msg_setint ) )
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
ipc_setdefmsg( _funcs, msg_default );
|
||||
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver: self
|
||||
selector: @selector(newclient:)
|
||||
name: NSFileHandleConnectionAcceptedNotification
|
||||
object: _listen];
|
||||
[_listen acceptConnectionInBackgroundAndNotify];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
struct sockaddr_un sun;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver: self];
|
||||
[_listen release];
|
||||
[_sock release];
|
||||
[_clients release];
|
||||
ipc_freemsgs( _funcs );
|
||||
getaddr( &sun );
|
||||
unlink( sun.sun_path );
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id) delegate
|
||||
{
|
||||
return _delegate;
|
||||
}
|
||||
|
||||
- (void) setDelegate: (id) newdelegate
|
||||
{
|
||||
_delegate = newdelegate;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IPCController (Private)
|
||||
|
||||
- (void) newclient: (NSNotification *) notification
|
||||
{
|
||||
NSDictionary * info;
|
||||
NSFileHandle * handle;
|
||||
NSNumber * error;
|
||||
IPCClient * client;
|
||||
|
||||
info = [notification userInfo];
|
||||
handle = [info objectForKey: NSFileHandleNotificationFileHandleItem];
|
||||
error = [info objectForKey: @"NSFileHandleError"];
|
||||
|
||||
if( nil != error )
|
||||
{
|
||||
NSLog( @"Failed to accept IPC socket connection: %@", error );
|
||||
return;
|
||||
}
|
||||
|
||||
[_listen acceptConnectionInBackgroundAndNotify];
|
||||
|
||||
if( nil == handle )
|
||||
return;
|
||||
|
||||
client = [[IPCClient alloc]
|
||||
initClient: self
|
||||
funcs: _funcs
|
||||
handle: handle];
|
||||
if( nil == client )
|
||||
return;
|
||||
|
||||
[_clients addObject:client];
|
||||
[client release];
|
||||
}
|
||||
|
||||
- (void) killclient: (IPCClient *) client
|
||||
{
|
||||
[_clients removeObject: client];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation IPCClient
|
||||
|
||||
- (id) initClient: (IPCController *) controller
|
||||
funcs: (struct ipc_funcs *) funcs
|
||||
handle: (NSFileHandle *) handle
|
||||
{
|
||||
uint8_t * buf;
|
||||
size_t size;
|
||||
|
||||
self = [super init];
|
||||
if( nil == self )
|
||||
return nil;
|
||||
|
||||
_handle = [handle retain];
|
||||
ipc_newcon( &_ipc, funcs );
|
||||
_controller = controller;
|
||||
_buf = [[NSMutableData alloc] init];
|
||||
|
||||
buf = ipc_mkvers( &size );
|
||||
if( nil == _buf || NULL == buf || ![self sendresp: buf size: size] )
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver: self
|
||||
selector: @selector(gotdata:)
|
||||
name: NSFileHandleReadCompletionNotification
|
||||
object: _handle];
|
||||
[_handle readInBackgroundAndNotify];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver: self];
|
||||
[_handle release];
|
||||
[_buf release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (IPCController *) controller
|
||||
{
|
||||
return _controller;
|
||||
}
|
||||
|
||||
- (struct ipc_info *) ipc
|
||||
{
|
||||
return &_ipc;
|
||||
}
|
||||
|
||||
- (void) gotdata: (NSNotification *) notification
|
||||
{
|
||||
NSDictionary * info;
|
||||
NSData * data;
|
||||
NSNumber * error;
|
||||
ssize_t res;
|
||||
|
||||
info = [notification userInfo];
|
||||
data = [info objectForKey: NSFileHandleNotificationDataItem];
|
||||
error = [info objectForKey: @"NSFileHandleError"];
|
||||
|
||||
if( nil != error )
|
||||
{
|
||||
NSLog( @"Failed to read from IPC socket connection: %@", error );
|
||||
[_controller killclient: self];
|
||||
return;
|
||||
}
|
||||
|
||||
if( nil == data || 0 == [data length] )
|
||||
{
|
||||
[_controller killclient: self];
|
||||
return;
|
||||
}
|
||||
|
||||
[_handle readInBackgroundAndNotify];
|
||||
[_buf appendData: data];
|
||||
|
||||
if( IPC_MIN_MSG_LEN > [_buf length] )
|
||||
return;
|
||||
|
||||
res = ipc_parse( &_ipc, [_buf mutableBytes], [_buf length], self );
|
||||
|
||||
if( 0 > res )
|
||||
{
|
||||
switch( errno )
|
||||
{
|
||||
case EPERM:
|
||||
NSLog( @"IPC client has unsupported protocol version" );
|
||||
break;
|
||||
case EINVAL:
|
||||
NSLog( @"IPC protocol parse error" );
|
||||
break;
|
||||
default:
|
||||
NSLog( @"IPC parsing failed" );
|
||||
break;
|
||||
}
|
||||
[_controller killclient: self];
|
||||
return;
|
||||
}
|
||||
else if( 0 < res )
|
||||
{
|
||||
if( res > [_buf length])
|
||||
{
|
||||
memmove( [_buf mutableBytes], [_buf bytes] + res,
|
||||
[_buf length] - res );
|
||||
}
|
||||
[_buf setLength: ([_buf length] - res)];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) sendresp: (uint8_t *) buf
|
||||
size: (size_t) size
|
||||
{
|
||||
@try
|
||||
{
|
||||
[_handle writeData: [NSData dataWithBytesNoCopy: buf
|
||||
length: size
|
||||
freeWhenDone: YES]];
|
||||
return YES;
|
||||
}
|
||||
@catch( NSException * ex )
|
||||
{
|
||||
NSLog( @"Failed to write to IPC socket connection" );
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) sendrespEmpty: (enum ipc_msg) msgid
|
||||
tag: (int64_t) tag
|
||||
{
|
||||
uint8_t * buf;
|
||||
size_t size;
|
||||
|
||||
buf = ipc_mkempty( &_ipc, &size, msgid, tag );
|
||||
if( NULL == buf )
|
||||
return FALSE;
|
||||
|
||||
return [self sendresp: buf
|
||||
size: size];
|
||||
}
|
||||
|
||||
- (BOOL) sendrespInt: (enum ipc_msg) msgid
|
||||
tag: (int64_t) tag
|
||||
val: (int64_t) val
|
||||
{
|
||||
uint8_t * buf;
|
||||
size_t size;
|
||||
|
||||
buf = ipc_mkint( &_ipc, &size, msgid, tag, val );
|
||||
if( NULL == buf )
|
||||
return FALSE;
|
||||
|
||||
return [self sendresp: buf
|
||||
size: size];
|
||||
}
|
||||
|
||||
- (BOOL) sendrespStr: (enum ipc_msg) msgid
|
||||
tag: (int64_t) tag
|
||||
val: (NSString *) val
|
||||
{
|
||||
uint8_t * buf;
|
||||
size_t size;
|
||||
NSData * data;
|
||||
NSMutableData * sucky;
|
||||
|
||||
if( [val canBeConvertedToEncoding: NSUTF8StringEncoding] )
|
||||
buf = ipc_mkstr( &_ipc, &size, msgid, tag,
|
||||
[val cStringUsingEncoding: NSUTF8StringEncoding] );
|
||||
else
|
||||
{
|
||||
data = [val dataUsingEncoding: NSUTF8StringEncoding
|
||||
allowLossyConversion: YES];
|
||||
/* XXX this sucks, I should add a length argument to ipc_mkstr() */
|
||||
sucky = [NSMutableData dataWithData: data];
|
||||
[sucky appendBytes: "" length: 1];
|
||||
buf = ipc_mkstr( &_ipc, &size, msgid, tag, [sucky bytes] );
|
||||
}
|
||||
if( NULL == buf )
|
||||
return FALSE;
|
||||
|
||||
return [self sendresp: buf
|
||||
size: size];
|
||||
}
|
||||
|
||||
- (void) sendrespInfo: (enum ipc_msg) respid
|
||||
tag: (int64_t) tag
|
||||
torrents: (NSArray *) tors
|
||||
types: (int) types
|
||||
{
|
||||
benc_val_t packet, * pkinf;
|
||||
NSEnumerator * enumerator;
|
||||
Torrent * tor;
|
||||
uint8_t * buf;
|
||||
size_t size;
|
||||
int res;
|
||||
|
||||
pkinf = ipc_initval( &_ipc, respid, tag, &packet, TYPE_LIST );
|
||||
if( NULL == pkinf )
|
||||
goto fail;
|
||||
if( tr_bencListReserve( pkinf, [tors count] ) )
|
||||
{
|
||||
tr_bencFree( &packet );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
enumerator = [tors objectEnumerator];
|
||||
while( nil != ( tor = [enumerator nextObject] ) )
|
||||
{
|
||||
if( IPC_MSG_INFO == respid )
|
||||
res = ipc_addinfo( pkinf, [tor getID], [tor getInfo], types );
|
||||
else
|
||||
res = ipc_addstat( pkinf, [tor getID], [tor getInfo],
|
||||
[tor getStat], types );
|
||||
if( 0 > res )
|
||||
{
|
||||
tr_bencFree( &packet );
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
buf = ipc_mkval( &packet, &size );
|
||||
tr_bencFree( &packet );
|
||||
if( NULL == buf )
|
||||
goto fail;
|
||||
[self sendresp: buf size: size ];
|
||||
return;
|
||||
|
||||
fail:
|
||||
NSLog( @"Failed to create IPC reply packet" );
|
||||
[_controller killclient: self];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
void
|
||||
getaddr( struct sockaddr_un * sun )
|
||||
{
|
||||
bzero( sun, sizeof *sun );
|
||||
sun->sun_family = AF_LOCAL;
|
||||
strlcpy( sun->sun_path, tr_getPrefsDirectory(), sizeof sun->sun_path );
|
||||
strlcat( sun->sun_path, "/socket", sizeof sun->sun_path );
|
||||
}
|
||||
|
||||
NSArray *
|
||||
bencarray( benc_val_t * val, int type )
|
||||
{
|
||||
int ii;
|
||||
NSMutableArray * ret;
|
||||
benc_val_t * item;
|
||||
|
||||
assert( TYPE_STR == type || TYPE_INT == type );
|
||||
|
||||
if( NULL == val || TYPE_LIST != val->type )
|
||||
return nil;
|
||||
|
||||
ret = [NSMutableArray arrayWithCapacity: val->val.l.count];
|
||||
for( ii = 0; ii < val->val.l.count; ii++ )
|
||||
{
|
||||
item = &val->val.l.vals[ii];
|
||||
if( type != item->type )
|
||||
return nil;
|
||||
if( TYPE_STR == type )
|
||||
{
|
||||
[ret addObject: [NSString stringWithCString: item->val.s.s
|
||||
encoding: NSUTF8StringEncoding]];
|
||||
}
|
||||
else
|
||||
{
|
||||
[ret addObject: [NSNumber numberWithLongLong: (long long) item->val.i]];
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
msg_lookup( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg )
|
||||
{
|
||||
IPCClient * client = arg;
|
||||
NSArray * hashes, * tors;
|
||||
benc_val_t packet, * pkinf;
|
||||
NSEnumerator * enumerator;
|
||||
Torrent * tor;
|
||||
uint8_t * buf;
|
||||
size_t size;
|
||||
|
||||
hashes = bencarray( val, TYPE_STR );
|
||||
if( NULL == hashes )
|
||||
{
|
||||
[client sendrespEmpty: IPC_MSG_NOTSUP tag: tag];
|
||||
return;
|
||||
}
|
||||
|
||||
tors = [[[client controller] delegate] ipcGetTorrentsByHash: hashes];
|
||||
[client sendrespInfo: IPC_MSG_INFO
|
||||
tag: tag
|
||||
torrents: tors
|
||||
types: IPC_INF_HASH];
|
||||
}
|
||||
|
||||
void
|
||||
msg_info( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg )
|
||||
{
|
||||
IPCClient * client = arg;
|
||||
enum ipc_msg respid;
|
||||
benc_val_t * typesval;
|
||||
int types;
|
||||
NSArray * ids, * tors;
|
||||
|
||||
if( NULL == val || TYPE_DICT != val->type )
|
||||
goto bad;
|
||||
|
||||
typesval = tr_bencDictFind( val, "type" );
|
||||
if( NULL == typesval || TYPE_LIST != typesval->type ||
|
||||
nil == ( ids = bencarray( tr_bencDictFind( val, "id" ), TYPE_INT ) ) )
|
||||
goto bad;
|
||||
|
||||
respid = ( IPC_MSG_GETINFO == msgid ? IPC_MSG_INFO : IPC_MSG_STAT );
|
||||
tors = [[[client controller] delegate] ipcGetTorrentsByID: ids];
|
||||
types = ipc_infotypes( respid, typesval );
|
||||
[client sendrespInfo: respid tag: tag torrents: tors types: types];
|
||||
return;
|
||||
|
||||
bad:
|
||||
NSLog( @"Got bad IPC packet" );
|
||||
[client sendrespEmpty: IPC_MSG_NOTSUP tag: tag];
|
||||
}
|
||||
|
||||
void
|
||||
msg_infoall( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg )
|
||||
{
|
||||
IPCClient * client = arg;
|
||||
enum ipc_msg respid;
|
||||
int types;
|
||||
NSArray * tors;
|
||||
|
||||
if( NULL == val || TYPE_LIST != val->type )
|
||||
{
|
||||
NSLog( @"Got bad IPC packet" );
|
||||
[client sendrespEmpty: IPC_MSG_NOTSUP tag: tag];
|
||||
return;
|
||||
}
|
||||
|
||||
respid = ( IPC_MSG_GETINFOALL == msgid ? IPC_MSG_INFO : IPC_MSG_STAT );
|
||||
tors = [[[client controller] delegate] ipcGetTorrentsByID: nil];
|
||||
types = ipc_infotypes( respid, val );
|
||||
[client sendrespInfo: respid tag: tag torrents: tors types: types];
|
||||
}
|
||||
|
||||
void
|
||||
msg_action( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg )
|
||||
{
|
||||
IPCClient * client = arg;
|
||||
BOOL res;
|
||||
NSArray * ids, * tors;
|
||||
id delegate;
|
||||
|
||||
ids = bencarray( val, TYPE_INT );
|
||||
if( nil == ids )
|
||||
{
|
||||
NSLog( @"Got bad IPC packet" );
|
||||
[client sendrespEmpty: IPC_MSG_NOTSUP tag: tag];
|
||||
return;
|
||||
}
|
||||
|
||||
delegate = [[client controller] delegate];
|
||||
tors = [delegate ipcGetTorrentsByID: ids];
|
||||
switch( msgid )
|
||||
{
|
||||
case IPC_MSG_REMOVE:
|
||||
res = [delegate ipcRemoveTorrents: tors];
|
||||
break;
|
||||
case IPC_MSG_START:
|
||||
res = [delegate ipcStartTorrents: tors];
|
||||
break;
|
||||
case IPC_MSG_STOP:
|
||||
res = [delegate ipcStopTorrents: tors];
|
||||
break;
|
||||
default:
|
||||
assert( 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
if( res )
|
||||
[client sendrespEmpty: IPC_MSG_OK tag: tag];
|
||||
else
|
||||
[client sendrespEmpty: IPC_MSG_FAIL tag: tag];
|
||||
}
|
||||
|
||||
void
|
||||
msg_actionall( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg )
|
||||
{
|
||||
IPCClient * client = arg;
|
||||
BOOL res;
|
||||
NSArray * tors;
|
||||
id delegate;
|
||||
|
||||
delegate = [[client controller] delegate];
|
||||
tors = [delegate ipcGetTorrentsByID: nil];
|
||||
switch( msgid )
|
||||
{
|
||||
case IPC_MSG_REMOVEALL:
|
||||
res = [delegate ipcRemoveTorrents: tors];
|
||||
break;
|
||||
case IPC_MSG_STARTALL:
|
||||
res = [delegate ipcStartTorrents: tors];
|
||||
break;
|
||||
case IPC_MSG_STOPALL:
|
||||
res = [delegate ipcStopTorrents: tors];
|
||||
break;
|
||||
default:
|
||||
assert( 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
if( res )
|
||||
[client sendrespEmpty: IPC_MSG_OK tag: tag];
|
||||
else
|
||||
[client sendrespEmpty: IPC_MSG_FAIL tag: tag];
|
||||
}
|
||||
|
||||
void
|
||||
msg_addold( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg )
|
||||
{
|
||||
IPCClient * client = arg;
|
||||
NSArray * paths;
|
||||
BOOL res;
|
||||
|
||||
paths = bencarray( val, TYPE_STR );
|
||||
if( nil == paths )
|
||||
{
|
||||
NSLog( @"Got bad IPC packet" );
|
||||
[client sendrespEmpty: IPC_MSG_NOTSUP tag: tag];
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX should send back info message with torrent IDs */
|
||||
if( [[[client controller] delegate] ipcAddTorrents: paths] )
|
||||
[client sendrespEmpty: IPC_MSG_OK tag: tag];
|
||||
else
|
||||
[client sendrespEmpty: IPC_MSG_FAIL tag: tag];
|
||||
}
|
||||
|
||||
void
|
||||
msg_addnew( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg )
|
||||
{
|
||||
IPCClient * client = arg;
|
||||
benc_val_t * fileval, * dataval, * dirval, * autoval;
|
||||
NSString * file, * dir;
|
||||
NSData * data;
|
||||
BOOL autobool, res;
|
||||
|
||||
if( NULL == val || TYPE_DICT != val->type )
|
||||
goto bad;
|
||||
|
||||
fileval = tr_bencDictFind( val, "file" );
|
||||
dataval = tr_bencDictFind( val, "data" );
|
||||
dirval = tr_bencDictFind( val, "directory" );
|
||||
autoval = tr_bencDictFind( val, "autostart" );
|
||||
if( ( ( NULL == fileval || TYPE_STR != fileval->type ) &&
|
||||
( NULL == dataval || TYPE_STR != dataval->type ) ) ||
|
||||
( ( NULL != fileval && TYPE_STR == fileval->type ) &&
|
||||
( NULL != dataval && TYPE_STR == dataval->type ) ) ||
|
||||
( NULL != dirval && TYPE_STR != dirval->type ) ||
|
||||
( NULL != autoval && TYPE_INT != autoval->type ) )
|
||||
goto bad;
|
||||
|
||||
dir = ( NULL == dirval ? nil :
|
||||
[NSString stringWithCString: dirval->val.s.s
|
||||
encoding: NSUTF8StringEncoding] );
|
||||
autobool = ( NULL == autoval || 0 == autoval->val.i ? NO : YES );
|
||||
|
||||
if( NULL != fileval )
|
||||
{
|
||||
file = [NSString stringWithCString: fileval->val.s.s
|
||||
encoding: NSUTF8StringEncoding];
|
||||
if( NULL == autoval )
|
||||
res = [[[client controller] delegate]
|
||||
ipcAddTorrentFile: file
|
||||
directory: dir];
|
||||
else
|
||||
res = [[[client controller] delegate]
|
||||
ipcAddTorrentFileAutostart: file
|
||||
directory: dir
|
||||
autostart: autobool];
|
||||
}
|
||||
else
|
||||
{
|
||||
data = [NSData dataWithBytes: dataval->val.s.s
|
||||
length: dataval->val.s.i];
|
||||
if( NULL == autoval )
|
||||
res = [[[client controller] delegate]
|
||||
ipcAddTorrentData: data
|
||||
directory: dir];
|
||||
else
|
||||
res = [[[client controller] delegate]
|
||||
ipcAddTorrentDataAutostart: data
|
||||
directory: dir
|
||||
autostart: autobool];
|
||||
}
|
||||
|
||||
/* XXX should send back info message with torrent ID */
|
||||
if( res )
|
||||
[client sendrespEmpty: IPC_MSG_OK tag: tag];
|
||||
else
|
||||
[client sendrespEmpty: IPC_MSG_FAIL tag: tag];
|
||||
return;
|
||||
|
||||
bad:
|
||||
NSLog( @"Got bad IPC packet" );
|
||||
[client sendrespEmpty: IPC_MSG_NOTSUP tag: tag];
|
||||
}
|
||||
|
||||
void
|
||||
msg_getbool( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg )
|
||||
{
|
||||
IPCClient * client = arg;
|
||||
|
||||
switch( msgid )
|
||||
{
|
||||
case IPC_MSG_GETAUTOMAP:
|
||||
case IPC_MSG_GETAUTOSTART:
|
||||
case IPC_MSG_GETPEX:
|
||||
[client sendrespEmpty: IPC_MSG_FAIL tag: tag];
|
||||
break;
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
msg_getint( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg )
|
||||
{
|
||||
IPCClient * client = arg;
|
||||
|
||||
switch( msgid )
|
||||
{
|
||||
case IPC_MSG_GETDOWNLIMIT:
|
||||
case IPC_MSG_GETPORT:
|
||||
case IPC_MSG_GETUPLIMIT:
|
||||
[client sendrespEmpty: IPC_MSG_FAIL tag: tag];
|
||||
break;
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
msg_getstr( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg )
|
||||
{
|
||||
IPCClient * client = arg;
|
||||
|
||||
switch( msgid )
|
||||
{
|
||||
case IPC_MSG_GETDIR:
|
||||
[client sendrespEmpty: IPC_MSG_FAIL tag: tag];
|
||||
break;
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
msg_setbool( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg )
|
||||
{
|
||||
IPCClient * client = arg;
|
||||
|
||||
if( NULL == val || TYPE_INT != val->type )
|
||||
{
|
||||
NSLog( @"Got bad IPC packet" );
|
||||
[client sendrespEmpty: IPC_MSG_NOTSUP tag: tag];
|
||||
return;
|
||||
}
|
||||
|
||||
switch( msgid )
|
||||
{
|
||||
case IPC_MSG_AUTOMAP:
|
||||
case IPC_MSG_AUTOSTART:
|
||||
case IPC_MSG_PEX:
|
||||
[client sendrespEmpty: IPC_MSG_FAIL tag: tag];
|
||||
break;
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
msg_setint( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg )
|
||||
{
|
||||
IPCClient * client = arg;
|
||||
|
||||
if( NULL == val || TYPE_INT != val->type )
|
||||
{
|
||||
NSLog( @"Got bad IPC packet" );
|
||||
[client sendrespEmpty: IPC_MSG_NOTSUP tag: tag];
|
||||
return;
|
||||
}
|
||||
|
||||
switch( msgid )
|
||||
{
|
||||
case IPC_MSG_DOWNLIMIT:
|
||||
case IPC_MSG_PORT:
|
||||
case IPC_MSG_UPLIMIT:
|
||||
[client sendrespEmpty: IPC_MSG_FAIL tag: tag];
|
||||
break;
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
msg_setstr( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg )
|
||||
{
|
||||
IPCClient * client = arg;
|
||||
|
||||
if( NULL == val || TYPE_STR != val->type )
|
||||
{
|
||||
NSLog( @"Got bad IPC packet" );
|
||||
[client sendrespEmpty: IPC_MSG_NOTSUP tag: tag];
|
||||
return;
|
||||
}
|
||||
|
||||
switch( msgid )
|
||||
{
|
||||
case IPC_MSG_DIR:
|
||||
[client sendrespEmpty: IPC_MSG_FAIL tag: tag];
|
||||
break;
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
msg_default( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg )
|
||||
{
|
||||
IPCClient * client = arg;
|
||||
|
||||
switch( msgid )
|
||||
{
|
||||
case IPC_MSG_NOOP:
|
||||
[client sendrespEmpty: IPC_MSG_OK tag: tag];
|
||||
break;
|
||||
case IPC_MSG_QUIT:
|
||||
[[[client controller] delegate] ipcQuit];
|
||||
[client sendrespEmpty: IPC_MSG_OK tag: tag];
|
||||
break;
|
||||
default:
|
||||
[client sendrespEmpty: IPC_MSG_NOTSUP tag: tag];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,8 @@
|
||||
tr_info_t * fInfo;
|
||||
tr_stat_t * fStat;
|
||||
|
||||
int fID;
|
||||
|
||||
BOOL fResumeOnWake;
|
||||
NSDate * fDateAdded, * fDateCompleted, * fAnnounceDate,
|
||||
* fDateActivity;
|
||||
@@ -212,4 +214,8 @@
|
||||
- (NSNumber *) progressSortKey;
|
||||
- (NSNumber *) ratioSortKey;
|
||||
|
||||
- (int) getID;
|
||||
- (tr_info_t *) getInfo;
|
||||
- (tr_stat_t *) getStat;
|
||||
|
||||
@end
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#define MAX_PIECES 324
|
||||
#define BLANK_PIECE -99
|
||||
|
||||
static int static_lastid = 0;
|
||||
|
||||
@interface Torrent (Private)
|
||||
|
||||
- (id) initWithHash: (NSString *) hashString path: (NSString *) path lib: (tr_handle_t *) lib
|
||||
@@ -1400,6 +1402,21 @@ static uint32_t kRed = BE(0xFF6450FF), //255, 100, 80
|
||||
return [NSNumber numberWithFloat: [self ratio]];
|
||||
}
|
||||
|
||||
- (int) getID
|
||||
{
|
||||
return fID;
|
||||
}
|
||||
|
||||
- (tr_info_t *) getInfo
|
||||
{
|
||||
return fInfo;
|
||||
}
|
||||
|
||||
- (tr_stat_t *) getStat
|
||||
{
|
||||
return fStat;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation Torrent (Private)
|
||||
@@ -1418,7 +1435,10 @@ static uint32_t kRed = BE(0xFF6450FF), //255, 100, 80
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
|
||||
static_lastid++;
|
||||
fID = static_lastid;
|
||||
|
||||
fLib = lib;
|
||||
fDefaults = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user