Permalink
Browse files

Merge pull request #21 from vicoapp/stream-sockets

Improve socket support in ViBufferedStream.
  • Loading branch information...
2 parents d094d60 + 38dc29b commit b956e998be8aa4f76e0ac58100ac8b6a698e90aa @martinh martinh committed Jul 16, 2012
Showing with 133 additions and 7 deletions.
  1. +14 −0 app/ViBufferedStream.h
  2. +119 −7 app/ViBufferedStream.m
View
14 app/ViBufferedStream.h
@@ -70,16 +70,30 @@
- (id)initWithTask:(NSTask *)task;
- (BOOL)bidirectional;
+- (id)initWithNode:(NSString *)node
+ service:(NSString *)service
+ type:(int)socktype
+ family:(int)family
+ protocol:(int)proto
+ error:(NSError **)outError;
+- (id)initWithHost:(NSString *)host port:(int)port;
++ (id)streamWithHost:(NSString *)host port:(int)port;
+- (id)initWithLocalSocket:(NSString *)file;
++ (id)streamWithLocalSocket:(NSString *)file;
+
- (BOOL)hasBytesAvailable;
- (BOOL)hasSpaceAvailable;
- (void)shutdownWrite;
- (void)shutdownRead;
+- (void)schedule;
+
- (BOOL)getBuffer:(const void **)buf length:(NSUInteger *)len;
- (NSData *)data;
- (void)write:(const void *)buf length:(NSUInteger)length;
- (void)writeData:(NSData *)data;
+- (void)writeString:(NSString *)aString;
@end
View
126 app/ViBufferedStream.m
@@ -23,15 +23,19 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/types.h>
+#include <sys/socket.h>
#include <sys/uio.h>
+#include <sys/un.h>
+#include <netdb.h>
+
#include <unistd.h>
#include <vis.h>
#import "ViBufferedStream.h"
+#import "ViError.h"
#include "logging.h"
-void hexdump(const void *data, size_t len, const char *fmt, ...);
-
@implementation ViStreamBuffer
@synthesize ptr = _ptr;
@@ -113,7 +117,6 @@ - (void)read
} else {
DEBUG(@"read %zi bytes from fd %i", ret, _fd_in);
#ifndef NO_DEBUG
- hexdump(_buffer, ret, "read data:");
char *vis = malloc(ret*4+1);
strvisx(vis, _buffer, ret, VIS_WHITE);
DEBUG(@"read data: %s", vis);
@@ -158,10 +161,6 @@ - (int)flush
iov[i].iov_len = buf.left;
tot += buf.left;
i++;
-
-#ifndef NO_DEBUG
- hexdump(buf.ptr, buf.left, "enqueueing buffer:");
-#endif
}
if (tot == 0) {
@@ -391,6 +390,109 @@ - (id)initWithTask:(NSTask *)task
priority:5];
}
+- (id)initWithNode:(NSString *)node
+ service:(NSString *)service
+ type:(int)socktype
+ family:(int)family
+ protocol:(int)proto
+ error:(NSError **)outError
+{
+ struct sockaddr_un addr;
+ struct addrinfo hints;
+ struct addrinfo *ai, *ai0;
+ int res, fd;
+
+ if (family == AF_UNSPEC && [node hasPrefix:@"/"]) {
+ family = AF_UNIX;
+ }
+
+ if (family == AF_UNIX) {
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ if (strlcpy(addr.sun_path, [node UTF8String], sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) {
+ if (outError) {
+ *outError = [ViError errorWithFormat:@"Path truncated."];
+ }
+ [self release];
+ return nil;
+ }
+ fd = socket(family, socktype, proto);
+ if (fd >= 0 && connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ close(fd);
+ fd = -1;
+ }
+ } else {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = socktype;
+ hints.ai_protocol = proto;
+
+ /* This does blocking DNS resolving. */
+ res = getaddrinfo([node UTF8String], [service UTF8String], &hints, &ai0);
+ if (res != 0) {
+ if (outError) {
+ *outError = [ViError errorWithFormat:@"%@", gai_strerror(res)];
+ }
+ [self release];
+ return nil;
+ }
+
+ for (ai = ai0; ai; ai = ai->ai_next) {
+ fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (fd < 0) {
+ continue;
+ }
+ if (connect(fd, ai->ai_addr, ai->ai_addrlen) < 0) {
+ close(fd);
+ fd = -1;
+ continue;
+ }
+ break;
+ }
+ freeaddrinfo(ai0);
+ }
+
+ if (fd < 0) {
+ if (outError) {
+ *outError = [ViError errorWithFormat:@"Failed to connect to %@:%@: %@", node, service, strerror(errno)];
+ }
+ [self release];
+ return nil;
+ }
+
+ return [self initWithReadDescriptor:fd writeDescriptor:fd priority:5];
+}
+
+- (id)initWithHost:(NSString *)host port:(int)port
+{
+ return [self initWithNode:host
+ service:[NSString stringWithFormat:@"%i", port]
+ type:SOCK_STREAM
+ family:0
+ protocol:0
+ error:nil];
+}
+
++ (id)streamWithHost:(NSString *)host port:(int)port
+{
+ return [[[self alloc] initWithHost:host port:port] autorelease];
+}
+
+- (id)initWithLocalSocket:(NSString *)file
+{
+ return [self initWithNode:file
+ service:nil
+ type:SOCK_STREAM
+ family:AF_UNIX
+ protocol:0
+ error:nil];
+}
+
++ (id)streamWithLocalSocket:(NSString *)file
+{
+ return [[[self alloc] initWithLocalSocket:file] autorelease];
+}
+
- (void)open
{
INFO(@"%s", "open?");
@@ -453,6 +555,11 @@ - (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode
CFRunLoopAddSource([aRunLoop getCFRunLoop], _outputSource, (CFStringRef)mode);
}
+- (void)schedule
+{
+ [self scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
+}
+
- (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode
{
DEBUG(@"removing from mode %@", mode);
@@ -510,6 +617,11 @@ - (void)writeData:(NSData *)aData
}
}
+- (void)writeString:(NSString *)aString
+{
+ [self writeData:[aString dataUsingEncoding:NSUTF8StringEncoding]];
+}
+
- (id)propertyForKey:(NSString *)key
{
DEBUG(@"key is %@", key);

0 comments on commit b956e99

Please sign in to comment.