160 lines
4.4 KiB
C
160 lines
4.4 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <netinet/in.h>
|
|
#include <sys/socket.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
#include <CoreFoundation/CoreFoundation.h>
|
|
#include "plist_server.h"
|
|
#include "util.h"
|
|
|
|
#define TCP_PORT 1999
|
|
|
|
int send_progress_message(int socket, int progress, int total)
|
|
{
|
|
const void* keys[3] = {CFSTR("MessageType"), CFSTR("Progress"), CFSTR("Total")};
|
|
const void* values[3] = {CFSTR("Progress"), NULL, NULL};
|
|
|
|
CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &progress);
|
|
CFNumberRef number2 = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &total);
|
|
values[1] = number;
|
|
values[2] = number2;
|
|
CFDictionaryRef msg = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
|
CFRelease(number);
|
|
CFRelease(number2);
|
|
int res = send_object(socket, msg);
|
|
CFRelease(msg);
|
|
return res;
|
|
}
|
|
|
|
int send_object(int socket, CFTypeRef obj)
|
|
{
|
|
uint32_t len = 0;
|
|
int res = -1;
|
|
|
|
if(obj == NULL)
|
|
return res;
|
|
|
|
CFDataRef outdata = CFPropertyListCreateData(kCFAllocatorDefault, obj, kCFPropertyListXMLFormat_v1_0, 0, NULL);
|
|
if (outdata != NULL)
|
|
{
|
|
len = CFDataGetLength(outdata);
|
|
write(socket, &len, 4);
|
|
res = write(socket, CFDataGetBytePtr(outdata), CFDataGetLength(outdata));
|
|
CFRelease(outdata);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
int handle_client(int socket, CFDictionaryRef handlers)
|
|
{
|
|
uint32_t len=0;
|
|
uint32_t received,i;
|
|
CFDataRef data;
|
|
CFDictionaryRef plist;
|
|
CFTypeRef out = NULL;
|
|
uint8_t* buffer;
|
|
CFTypeRef (*handler)(int, CFDictionaryRef dict) = NULL;
|
|
|
|
while(1)
|
|
{
|
|
if(recv(socket, &len, 4, 0) != 4)
|
|
break;
|
|
//printf("len=%x\n", len);
|
|
|
|
if (len > PLIST_MAX_SIZE)
|
|
break;
|
|
|
|
buffer = malloc(len);
|
|
|
|
if(buffer == NULL)
|
|
break;
|
|
|
|
for(i=0; i < len; )
|
|
{
|
|
received = recv(socket, &buffer[i], len - i, 0);
|
|
if (received == -1)
|
|
break;
|
|
i += received;
|
|
}
|
|
|
|
data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, buffer, len, kCFAllocatorNull);
|
|
|
|
if(data == NULL)
|
|
{
|
|
free(buffer);
|
|
continue;
|
|
}
|
|
|
|
plist = (CFDictionaryRef) CFPropertyListCreateWithData (kCFAllocatorDefault, data, kCFPropertyListImmutable, NULL, NULL);
|
|
|
|
if(plist == NULL || CFGetTypeID(plist) != CFDictionaryGetTypeID())
|
|
{
|
|
CFRelease(data);
|
|
free(buffer);
|
|
send_object(socket, CFSTR("invalid XML plist dictionary"));
|
|
continue;
|
|
}
|
|
|
|
if (CFDictionaryContainsKey(plist, CFSTR("Request")))
|
|
{
|
|
CFStringRef request = CFDictionaryGetValue(plist, CFSTR("Request"));
|
|
|
|
handler = CFDictionaryGetValue(handlers, request);
|
|
|
|
if (handler != NULL)
|
|
{
|
|
out = handler(socket, plist);
|
|
if (out == NULL)
|
|
out = CFSTR("Request did not return any result");
|
|
}
|
|
else
|
|
{
|
|
out = CFSTR("No handler defined for Request");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
out = CFSTR("request dictionary needs to contain Request key");
|
|
}
|
|
|
|
if(out == NULL)
|
|
out = CFSTR("no response");
|
|
|
|
send_object(socket, out);
|
|
CFRelease(out);
|
|
|
|
CFRelease(plist);
|
|
CFRelease(data);
|
|
free(buffer);
|
|
}
|
|
send_object(socket, CFSTR("kthxbye"));
|
|
return 0;
|
|
}
|
|
|
|
void serve_plist_rpc(int port, CFDictionaryRef handlers)
|
|
{
|
|
int quit = 0;
|
|
int one=1;
|
|
printf("plist_rpc: listening on port %d\n", port);
|
|
int sl = create_listening_socket(port);
|
|
|
|
while(!quit)
|
|
{
|
|
int s = accept(sl, NULL, NULL);
|
|
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&one, sizeof(int));
|
|
|
|
handle_client(s, handlers);
|
|
shutdown(s, SHUT_RDWR);
|
|
close(s);
|
|
}
|
|
close(sl);
|
|
}
|
|
|
|
CFStringRef testHandler(int s, CFDictionaryRef dict)
|
|
{
|
|
printf("lol\n");
|
|
return CFSTR("Hello, World!");
|
|
}
|
|
|