#include #include #include #include #include #include #include #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!"); }