sogo/Tools/SOGoSockD.m

168 lines
4.1 KiB
Objective-C

/* SOGoSockD.m - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSData.h>
#import <Foundation/NSRunLoop.h>
#import <Foundation/NSUserDefaults.h>
#import <NGStreams/NGActiveSocket.h>
#import <NGStreams/NGLocalSocketAddress.h>
#import <NGStreams/NGPassiveSocket.h>
#import <NGExtensions/NSObject+Logs.h>
#import "SOGoSockDScanner.h"
#import "SOGoSockD.h"
@implementation SOGoSockD
- (void) _setupListeningSocket
{
NGLocalSocketAddress *address;
NSString *path;
NSUserDefaults *ud;
ud = [NSUserDefaults standardUserDefaults];
path = [ud stringForKey: @"SOGoSLAPDSocketPath"];
if (!path)
path = @"/var/run/sogo/sogo-sockd.sock";
address = [NGLocalSocketAddress addressWithPath: path];
ASSIGN (listeningSocket, [NGPassiveSocket socketBoundToAddress: address]);
[listeningSocket listenWithBacklog: 5];
[self logWithFormat: @"listening on %@", path];
}
- (BOOL) _startRunLoopWithSocket: (NGPassiveSocket *) socket
{
NSRunLoop *runLoop;
NSDate *limitDate;
BOOL terminate;
void *fdPtr;
runLoop = [NSRunLoop currentRunLoop];
#if LONG_MAX > INT_MAX
fdPtr = (void *) ([socket fileDescriptor] & 0xFFFFFFFFFFFFFFFF);
#else
fdPtr = (void *) [socket fileDescriptor];
#endif
[runLoop addEvent: fdPtr type: ET_RDESC
watcher: self forMode: NSDefaultRunLoopMode];
terminate = NO;
while (!terminate)
{
limitDate = [runLoop limitDateForMode: NSDefaultRunLoopMode];
[runLoop runMode: NSDefaultRunLoopMode beforeDate: limitDate];
}
return YES;
}
- (BOOL) run
{
BOOL rc;
[self _setupListeningSocket];
if (listeningSocket)
rc = [self _startRunLoopWithSocket: listeningSocket];
else
rc = NO;
return rc;
}
- (BOOL) _handleData: (NSData *) socketData
onSocket: (id <NGActiveSocket>) responseSocket
{
NSString *stringData;
SOGoSockDScanner *scanner;
SOGoSockDOperation *operation;
BOOL rc;
stringData = [[NSString alloc] initWithData: socketData
encoding: NSASCIIStringEncoding];
if (stringData)
{
scanner = [SOGoSockDScanner scannerWithString: stringData];
operation = [scanner operation];
if (operation)
{
rc = YES;
[operation respondOnSocket: (NGActiveSocket *) responseSocket];
}
else
rc = NO;
}
else
rc = NO;
return rc;
}
- (void) _acceptAndHandle
{
id <NGActiveSocket> socket;
char buffer[1024];
unsigned int count;
NSMutableData *socketData;
BOOL done;
NSAutoreleasePool *pool;
pool = [NSAutoreleasePool new];
socketData = [NSMutableData dataWithCapacity: 16384];
socket = [listeningSocket accept];
done = NO;
while (!done)
{
count = [socket readBytes: buffer count: 1024];
if (count == NGStreamError)
done = YES;
else
{
if (buffer[count-2] == '\n' && buffer[count-1] == '\n')
{
done = YES;
count -= 2;
}
[socketData appendBytes: buffer length: count];
[self _handleData: socketData onSocket: socket];
socketData = [NSMutableData dataWithCapacity: 16384];
}
}
[pool release];
}
- (void) receivedEvent: (void*) data
type: (RunLoopEventType) type
extra: (void*) extra
forMode: (NSString*) mode
{
if (type == ET_RDESC)
[self _acceptAndHandle];
}
@end