author | Michael Krelin <hacker@klever.net> | 2012-12-08 21:19:17 (UTC) |
---|---|---|
committer | Michael Krelin <hacker@klever.net> | 2012-12-11 21:59:29 (UTC) |
commit | 8808689fe340bec6e90ab13dd502292b0579cf1f (patch) (unidiff) | |
tree | 45b7c863151341f687b74e40bffcbd7ab5468783 /pumpkin/DaemonListener.m | |
parent | 6e7e413ca364d79673e523c09767c18e7cff1bec (diff) | |
download | pumpkin-osx/0.0.zip pumpkin-osx/0.0.tar.gz pumpkin-osx/0.0.tar.bz2 |
initial osx portosx/0.0
Signed-off-by: Michael Krelin <hacker@klever.net>
-rw-r--r-- | pumpkin/DaemonListener.m | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/pumpkin/DaemonListener.m b/pumpkin/DaemonListener.m new file mode 100644 index 0000000..ab14296 --- a/dev/null +++ b/pumpkin/DaemonListener.m | |||
@@ -0,0 +1,111 @@ | |||
1 | #import "DaemonListener.h" | ||
2 | #import "TFTPPacket.h" | ||
3 | #import "SendXFer.h" | ||
4 | #import "ReceiveXFer.h" | ||
5 | #import "StringsAttached.h" | ||
6 | |||
7 | #include <sys/socket.h> | ||
8 | #include <arpa/inet.h> | ||
9 | #include <sys/stat.h> | ||
10 | |||
11 | static void cbListener(CFSocketRef sockie,CFSocketCallBackType cbt,CFDataRef cba, | ||
12 | const void *cbd,void *i) { | ||
13 | [(DaemonListener*)i callbackWithType:cbt addr:cba data:cbd]; | ||
14 | } | ||
15 | |||
16 | @implementation DaemonListener | ||
17 | |||
18 | -(void)callbackWithType:(CFSocketCallBackType)t addr:(CFDataRef)a data:(const void *)d { | ||
19 | switch(t) { | ||
20 | case kCFSocketDataCallBack: | ||
21 | { | ||
22 | struct sockaddr_in *sin = (struct sockaddr_in*)CFDataGetBytePtr(a); | ||
23 | if([pumpkin hasPeer:sin]) { | ||
24 | [pumpkin log:@"I'm already processing the request from %@",[NSString stringWithSocketAddress:sin]]; | ||
25 | return; | ||
26 | } | ||
27 | TFTPPacket *p = [TFTPPacket packetWithData:(NSData*)d]; | ||
28 | switch([p op]) { | ||
29 | case tftpOpRRQ: [[[SendXFer alloc] initWithPeer:sin andPacket:p] autorelease]; break; | ||
30 | case tftpOpWRQ: [[[ReceiveXFer alloc] initWithPeer:sin andPacket:p] autorelease]; break; | ||
31 | default: | ||
32 | [pumpkin log:@"Invalid OP %d received from %@",p.op,[NSString stringWithSocketAddress:sin]]; | ||
33 | break; | ||
34 | } | ||
35 | } | ||
36 | break; | ||
37 | default: | ||
38 | NSLog(@"unhandled callback: %lu",t); | ||
39 | break; | ||
40 | } | ||
41 | } | ||
42 | |||
43 | |||
44 | -(DaemonListener*)initWithAddress:(struct sockaddr_in*)sin { | ||
45 | if(!(self=[super init])) return self; | ||
46 | |||
47 | pumpkin = NSApplication.sharedApplication.delegate; | ||
48 | |||
49 | @try { | ||
50 | CFSocketContext ctx; | ||
51 | ctx.version = 0; | ||
52 | ctx.info = self; | ||
53 | ctx.retain = 0; ctx.release = 0; | ||
54 | ctx.copyDescription = 0; | ||
55 | sockie = CFSocketCreate(kCFAllocatorDefault,PF_INET,SOCK_DGRAM,IPPROTO_UDP, | ||
56 | kCFSocketReadCallBack|kCFSocketDataCallBack, | ||
57 | cbListener,&ctx); | ||
58 | if(ntohs(sin->sin_port)>1024) { | ||
59 | NSData *nsd = [NSData dataWithBytes:sin length:sizeof(*sin)]; | ||
60 | if(CFSocketSetAddress(sockie, (CFDataRef)nsd)) | ||
61 | [[NSException exceptionWithName:@"BindFailure" | ||
62 | reason:[NSString stringWithFormat:@"Binding failed, error code: %d", errno] | ||
63 | userInfo:@{@"errno": @errno} | ||
64 | ] raise]; | ||
65 | }else{ | ||
66 | const char *args[] = { | ||
67 | 0, | ||
68 | [[NSString stringWithFormat:@"%d", CFSocketGetNative(sockie)] UTF8String], | ||
69 | [[NSString stringWithHostAddress:sin] UTF8String], | ||
70 | [[NSString stringWithPortNumber:sin] UTF8String], | ||
71 | NULL | ||
72 | }; | ||
73 | [pumpkin runBiportal:args]; | ||
74 | } | ||
75 | }@catch(NSException *e) { | ||
76 | if(sockie) { | ||
77 | CFSocketInvalidate(sockie); | ||
78 | CFRelease(sockie); | ||
79 | } | ||
80 | @throw; | ||
81 | } | ||
82 | |||
83 | runloopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, sockie, 0); | ||
84 | CFRunLoopAddSource(CFRunLoopGetCurrent(),runloopSource, kCFRunLoopDefaultMode); | ||
85 | return self; | ||
86 | } | ||
87 | |||
88 | -(void)dealloc { | ||
89 | if(runloopSource) { | ||
90 | CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runloopSource, kCFRunLoopDefaultMode); | ||
91 | CFRelease(runloopSource); | ||
92 | } | ||
93 | if(sockie) { | ||
94 | CFSocketInvalidate(sockie); | ||
95 | CFRelease(sockie); | ||
96 | } | ||
97 | [super dealloc]; | ||
98 | } | ||
99 | |||
100 | +(DaemonListener*) listenerWithDefaults { | ||
101 | struct sockaddr_in sin; | ||
102 | memset(&sin,0,sizeof(sin)); | ||
103 | sin.sin_len=sizeof(sin); | ||
104 | sin.sin_family=AF_INET; | ||
105 | id d = [[NSUserDefaultsController sharedUserDefaultsController] values]; | ||
106 | sin.sin_port=htons([[d valueForKey:@"bindPort"] intValue]); | ||
107 | sin.sin_addr.s_addr=inet_addr([[d valueForKey:@"bindAddress"] UTF8String]); | ||
108 | return [[[DaemonListener alloc] initWithAddress:&sin] autorelease]; | ||
109 | } | ||
110 | |||
111 | @end | ||