Make non-blocking processing possible.

FossilOrigin-Name: 8b4878957125416dad0f0a91a2b64ae63c8284e39286e70eb7ae15086ef90307
This commit is contained in:
Jonathan Schleifer 2011-09-14 23:38:35 +00:00
parent a8b7db8d28
commit 8057b5df61
2 changed files with 275 additions and 275 deletions

View file

@ -107,5 +107,6 @@
fromChannel: (IRCChannel*)channel
withReason: (OFString*)reason;
- (void)changeNicknameTo: (OFString*)nickname;
- (void)process;
- (void)handleConnection;
@end

View file

@ -163,288 +163,287 @@
[self sendLineWithFormat: @"NICK %@", nickname_];
}
- (void)handleConnection
- (void)process
{
OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
OFString *line;
OFArray *split;
OFString *action = nil;
for (;;) {
OFString *action = nil;
@try {
line = [sock readLine];
} @catch (OFInvalidEncodingException *e) {
[e dealloc];
line = [sock readLineWithEncoding:
OF_STRING_ENCODING_WINDOWS_1252];
}
if (line == nil)
break;
if ([delegate respondsToSelector:
@selector(connection:didReceiveLine:)])
[delegate connection: self
didReceiveLine: line];
split = [line componentsSeparatedByString: @" "];
/* PING */
if (split.count == 2 && [split.firstObject isEqual: @"PING"]) {
OFMutableString *s = [[line mutableCopy] autorelease];
[s replaceOccurrencesOfString: @"PING"
withString: @"PONG"];
[self sendLine: s];
continue;
}
action = [[split objectAtIndex: 1] uppercaseString];
/* Connected */
if ([action isEqual: @"001"] && split.count >= 4) {
if ([delegate respondsToSelector:
@selector(connectionWasEstablished:)])
[delegate connectionWasEstablished: self];
continue;
}
/* JOIN */
if ([action isEqual: @"JOIN"] && split.count == 3) {
OFString *who = [split objectAtIndex: 0];
OFString *where = [split objectAtIndex: 2];
IRCUser *user;
IRCChannel *channel;
who = [who substringWithRange:
of_range(1, who.length - 1)];
where = [where substringWithRange:
of_range(1, where.length - 1)];
user = [IRCUser IRCUserWithString: who];
if ([who hasPrefix:
[nickname stringByAppendingString: @"!"]]) {
channel = [IRCChannel channelWithName: where];
[channels setObject: channel
forKey: where];
} else
channel = [channels objectForKey: where];
if ([delegate respondsToSelector:
@selector(connection:didSeeUser:joinChannel:)])
[delegate connection: self
didSeeUser: user
joinChannel: channel];
continue;
}
/* PART */
if ([action isEqual: @"PART"] && split.count >= 3) {
OFString *who = [split objectAtIndex: 0];
OFString *where = [split objectAtIndex: 2];
IRCUser *user;
IRCChannel *channel;
OFString *reason = nil;
size_t pos = who.length + 1 +
[[split objectAtIndex: 1] length] + 1 +
where.length;
who = [who substringWithRange:
of_range(1, who.length - 1)];
user = [IRCUser IRCUserWithString: who];
channel = [channels objectForKey: where];
if (split.count > 3)
reason = [line substringWithRange:
of_range(pos + 2, line.length - pos - 2)];
if ([delegate respondsToSelector:
@selector(connection:didSeeUser:leaveChannel:
withReason:)])
[delegate connection: self
didSeeUser: user
leaveChannel: channel
withReason: reason];
continue;
}
/* KICK */
if ([action isEqual: @"KICK"] && split.count >= 4) {
OFString *who = [split objectAtIndex: 0];
OFString *where = [split objectAtIndex: 2];
OFString *whom = [split objectAtIndex: 3];
IRCUser *user;
IRCChannel *channel;
OFString *reason = nil;
size_t pos = who.length + 1 +
[[split objectAtIndex: 1] length] + 1 +
where.length + 1 + whom.length;
who = [who substringWithRange:
of_range(1, who.length - 1)];
user = [IRCUser IRCUserWithString: who];
channel = [channels objectForKey: where];
if (split.count > 4)
reason = [line substringWithRange:
of_range(pos + 2, line.length - pos - 2)];
if ([delegate respondsToSelector:
@selector(connection:didSeeUser:kickUser:
fromChannel:withReason:)])
[delegate connection: self
didSeeUser: user
kickUser: whom
fromChannel: channel
withReason: reason];
continue;
}
/* QUIT */
if ([action isEqual: @"QUIT"] && split.count >= 2) {
OFString *who = [split objectAtIndex: 0];
IRCUser *user;
OFString *reason = nil;
size_t pos = who.length + 1 +
[[split objectAtIndex: 1] length];
who = [who substringWithRange:
of_range(1, who.length - 1)];
user = [IRCUser IRCUserWithString: who];
if (split.count > 2)
reason = [line substringWithRange:
of_range(pos + 2, line.length - pos - 2)];
if ([delegate respondsToSelector:
@selector(connection:didSeeUserQuit:withReason:)])
[delegate connection: self
didSeeUserQuit: user
withReason: reason];
continue;
}
/* NICK */
if ([action isEqual: @"NICK"] && split.count == 3) {
OFString *who = [split objectAtIndex: 0];
OFString *newNickname = [split objectAtIndex: 2];
IRCUser *user;
who = [who substringWithRange:
of_range(1, who.length - 1)];
newNickname = [newNickname substringWithRange:
of_range(1, newNickname.length - 1)];
user = [IRCUser IRCUserWithString: who];
if ([user.nickname isEqual: nickname]) {
[nickname release];
nickname = [user.nickname copy];
}
if ([delegate respondsToSelector:
@selector(connection:didSeeUser:changeNicknameTo:)])
[delegate connection: self
didSeeUser: user
changeNicknameTo: newNickname];
}
/* PRIVMSG */
if ([action isEqual: @"PRIVMSG"] && split.count >= 4) {
OFString *from = [split objectAtIndex: 0];
OFString *to = [split objectAtIndex: 2];
IRCUser *user;
OFString *msg;
size_t pos = from.length + 1 +
[[split objectAtIndex: 1] length] + 1 +
to.length;
from = [from substringWithRange:
of_range(1, from.length - 1)];
msg = [line substringWithRange:
of_range(pos + 2, line.length - pos - 2)];
user = [IRCUser IRCUserWithString: from];
if (![to isEqual: nickname]) {
IRCChannel *channel;
channel = [channels objectForKey: to];
if ([delegate respondsToSelector:
@selector(connection:didReceiveMessage:
fromUser:inChannel:)])
[delegate connection: self
didReceiveMessage: msg
fromUser: user
inChannel: channel];
} else {
if ([delegate respondsToSelector:
@selector(connection:
didReceivePrivateMessage:fromUser:)])
[delegate
connection: self
didReceivePrivateMessage: msg
fromUser: user];
}
continue;
}
/* NOTICE */
if ([action isEqual: @"NOTICE"] && split.count >= 4) {
OFString *from = [split objectAtIndex: 0];
OFString *to = [split objectAtIndex: 2];
IRCUser *user = nil;
OFString *notice;
size_t pos = from.length + 1 +
[[split objectAtIndex: 1] length] + 1 +
to.length;
from = [from substringWithRange:
of_range(1, from.length - 1)];
notice = [line substringWithRange:
of_range(pos + 2, line.length - pos - 2)];
if (![from containsString: @"!"] || [to isEqual: @"*"])
/* System message - ignore for now */
continue;
user = [IRCUser IRCUserWithString: from];
if (![to isEqual: nickname]) {
IRCChannel *channel;
channel = [channels objectForKey: to];
if ([delegate respondsToSelector:
@selector(connection:didReceiveNotice:
fromUser:inChannel:)])
[delegate connection: self
didReceiveNotice: notice
fromUser: user
inChannel: channel];
} else {
if ([delegate respondsToSelector:
@selector(connection:didReceiveNotice:
fromUser:)])
[delegate connection: self
didReceiveNotice: notice
fromUser: user];
}
continue;
}
[pool releaseObjects];
@try {
line = [sock tryReadLine];
} @catch (OFInvalidEncodingException *e) {
[e dealloc];
line = [sock tryReadLineWithEncoding:
OF_STRING_ENCODING_WINDOWS_1252];
}
[pool release];
if (line == nil)
return;
if ([delegate respondsToSelector:
@selector(connection:didReceiveLine:)])
[delegate connection: self
didReceiveLine: line];
split = [line componentsSeparatedByString: @" "];
/* PING */
if (split.count == 2 && [split.firstObject isEqual: @"PING"]) {
OFMutableString *s = [[line mutableCopy] autorelease];
[s replaceOccurrencesOfString: @"PING"
withString: @"PONG"];
[self sendLine: s];
return;
}
action = [[split objectAtIndex: 1] uppercaseString];
/* Connected */
if ([action isEqual: @"001"] && split.count >= 4) {
if ([delegate respondsToSelector:
@selector(connectionWasEstablished:)])
[delegate connectionWasEstablished: self];
[pool release];
return;
}
/* JOIN */
if ([action isEqual: @"JOIN"] && split.count == 3) {
OFString *who = [split objectAtIndex: 0];
OFString *where = [split objectAtIndex: 2];
IRCUser *user;
IRCChannel *channel;
who = [who substringWithRange: of_range(1, who.length - 1)];
where = [where substringWithRange:
of_range(1, where.length - 1)];
user = [IRCUser IRCUserWithString: who];
if ([who hasPrefix: [nickname stringByAppendingString: @"!"]]) {
channel = [IRCChannel channelWithName: where];
[channels setObject: channel
forKey: where];
} else
channel = [channels objectForKey: where];
if ([delegate respondsToSelector:
@selector(connection:didSeeUser:joinChannel:)])
[delegate connection: self
didSeeUser: user
joinChannel: channel];
[pool release];
return;
}
/* PART */
if ([action isEqual: @"PART"] && split.count >= 3) {
OFString *who = [split objectAtIndex: 0];
OFString *where = [split objectAtIndex: 2];
IRCUser *user;
IRCChannel *channel;
OFString *reason = nil;
size_t pos = who.length + 1 +
[[split objectAtIndex: 1] length] + 1 + where.length;
who = [who substringWithRange: of_range(1, who.length - 1)];
user = [IRCUser IRCUserWithString: who];
channel = [channels objectForKey: where];
if (split.count > 3)
reason = [line substringWithRange:
of_range(pos + 2, line.length - pos - 2)];
if ([delegate respondsToSelector:
@selector(connection:didSeeUser:leaveChannel:
withReason:)])
[delegate connection: self
didSeeUser: user
leaveChannel: channel
withReason: reason];
[pool release];
return;
}
/* KICK */
if ([action isEqual: @"KICK"] && split.count >= 4) {
OFString *who = [split objectAtIndex: 0];
OFString *where = [split objectAtIndex: 2];
OFString *whom = [split objectAtIndex: 3];
IRCUser *user;
IRCChannel *channel;
OFString *reason = nil;
size_t pos = who.length + 1 +
[[split objectAtIndex: 1] length] + 1 + where.length + 1 +
whom.length;
who = [who substringWithRange: of_range(1, who.length - 1)];
user = [IRCUser IRCUserWithString: who];
channel = [channels objectForKey: where];
if (split.count > 4)
reason = [line substringWithRange:
of_range(pos + 2, line.length - pos - 2)];
if ([delegate respondsToSelector:
@selector(connection:didSeeUser:kickUser:
fromChannel:withReason:)])
[delegate connection: self
didSeeUser: user
kickUser: whom
fromChannel: channel
withReason: reason];
[pool release];
return;
}
/* QUIT */
if ([action isEqual: @"QUIT"] && split.count >= 2) {
OFString *who = [split objectAtIndex: 0];
IRCUser *user;
OFString *reason = nil;
size_t pos = who.length + 1 + [[split objectAtIndex: 1] length];
who = [who substringWithRange: of_range(1, who.length - 1)];
user = [IRCUser IRCUserWithString: who];
if (split.count > 2)
reason = [line substringWithRange:
of_range(pos + 2, line.length - pos - 2)];
if ([delegate respondsToSelector:
@selector(connection:didSeeUserQuit:withReason:)])
[delegate connection: self
didSeeUserQuit: user
withReason: reason];
[pool release];
return;
}
/* NICK */
if ([action isEqual: @"NICK"] && split.count == 3) {
OFString *who = [split objectAtIndex: 0];
OFString *newNickname = [split objectAtIndex: 2];
IRCUser *user;
who = [who substringWithRange: of_range(1, who.length - 1)];
newNickname = [newNickname substringWithRange:
of_range(1, newNickname.length - 1)];
user = [IRCUser IRCUserWithString: who];
if ([user.nickname isEqual: nickname]) {
[nickname release];
nickname = [user.nickname copy];
}
if ([delegate respondsToSelector:
@selector(connection:didSeeUser:changeNicknameTo:)])
[delegate connection: self
didSeeUser: user
changeNicknameTo: newNickname];
[pool release];
return;
}
/* PRIVMSG */
if ([action isEqual: @"PRIVMSG"] && split.count >= 4) {
OFString *from = [split objectAtIndex: 0];
OFString *to = [split objectAtIndex: 2];
IRCUser *user;
OFString *msg;
size_t pos = from.length + 1 +
[[split objectAtIndex: 1] length] + 1 + to.length;
from = [from substringWithRange: of_range(1, from.length - 1)];
msg = [line substringWithRange:
of_range(pos + 2, line.length - pos - 2)];
user = [IRCUser IRCUserWithString: from];
if (![to isEqual: nickname]) {
IRCChannel *channel;
channel = [channels objectForKey: to];
if ([delegate respondsToSelector:
@selector(connection:didReceiveMessage:
fromUser:inChannel:)])
[delegate connection: self
didReceiveMessage: msg
fromUser: user
inChannel: channel];
} else {
if ([delegate respondsToSelector:
@selector(connection:
didReceivePrivateMessage:fromUser:)])
[delegate
connection: self
didReceivePrivateMessage: msg
fromUser: user];
}
[pool release];
return;
}
/* NOTICE */
if ([action isEqual: @"NOTICE"] && split.count >= 4) {
OFString *from = [split objectAtIndex: 0];
OFString *to = [split objectAtIndex: 2];
IRCUser *user = nil;
OFString *notice;
size_t pos = from.length + 1 +
[[split objectAtIndex: 1] length] + 1 + to.length;
from = [from substringWithRange: of_range(1, from.length - 1)];
notice = [line substringWithRange:
of_range(pos + 2, line.length - pos - 2)];
if (![from containsString: @"!"] || [to isEqual: @"*"]) {
/* System message - ignore for now */
[pool release];
return;
}
user = [IRCUser IRCUserWithString: from];
if (![to isEqual: nickname]) {
IRCChannel *channel;
channel = [channels objectForKey: to];
if ([delegate respondsToSelector:
@selector(connection:didReceiveNotice:
fromUser:inChannel:)])
[delegate connection: self
didReceiveNotice: notice
fromUser: user
inChannel: channel];
} else {
if ([delegate respondsToSelector:
@selector(connection:didReceiveNotice:
fromUser:)])
[delegate connection: self
didReceiveNotice: notice
fromUser: user];
}
[pool release];
return;
}
}
- (void)handleConnection
{
while (![sock isAtEndOfStream])
[self process];
}
- (void)dealloc