Skip to content
This repository
Browse code

Merge pull request #21 from vicoapp/stream-sockets

Improve socket support in ViBufferedStream.
  • Loading branch information...
commit b956e998be8aa4f76e0ac58100ac8b6a698e90aa 2 parents d094d60 + 38dc29b
martinh martinh authored

Showing 2 changed files with 133 additions and 7 deletions. Show diff stats Hide diff stats

  1. +14 0 app/ViBufferedStream.h
  2. +119 7 app/ViBufferedStream.m
14 app/ViBufferedStream.h
@@ -70,16 +70,30 @@
70 70 - (id)initWithTask:(NSTask *)task;
71 71 - (BOOL)bidirectional;
72 72
  73 +- (id)initWithNode:(NSString *)node
  74 + service:(NSString *)service
  75 + type:(int)socktype
  76 + family:(int)family
  77 + protocol:(int)proto
  78 + error:(NSError **)outError;
  79 +- (id)initWithHost:(NSString *)host port:(int)port;
  80 ++ (id)streamWithHost:(NSString *)host port:(int)port;
  81 +- (id)initWithLocalSocket:(NSString *)file;
  82 ++ (id)streamWithLocalSocket:(NSString *)file;
  83 +
73 84 - (BOOL)hasBytesAvailable;
74 85 - (BOOL)hasSpaceAvailable;
75 86
76 87 - (void)shutdownWrite;
77 88 - (void)shutdownRead;
78 89
  90 +- (void)schedule;
  91 +
79 92 - (BOOL)getBuffer:(const void **)buf length:(NSUInteger *)len;
80 93 - (NSData *)data;
81 94
82 95 - (void)write:(const void *)buf length:(NSUInteger)length;
83 96 - (void)writeData:(NSData *)data;
  97 +- (void)writeString:(NSString *)aString;
84 98
85 99 @end
126 app/ViBufferedStream.m
@@ -23,15 +23,19 @@
23 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 24 */
25 25
  26 +#include <sys/types.h>
  27 +#include <sys/socket.h>
26 28 #include <sys/uio.h>
  29 +#include <sys/un.h>
  30 +#include <netdb.h>
  31 +
27 32 #include <unistd.h>
28 33 #include <vis.h>
29 34
30 35 #import "ViBufferedStream.h"
  36 +#import "ViError.h"
31 37 #include "logging.h"
32 38
33   -void hexdump(const void *data, size_t len, const char *fmt, ...);
34   -
35 39 @implementation ViStreamBuffer
36 40
37 41 @synthesize ptr = _ptr;
@@ -113,7 +117,6 @@ - (void)read
113 117 } else {
114 118 DEBUG(@"read %zi bytes from fd %i", ret, _fd_in);
115 119 #ifndef NO_DEBUG
116   - hexdump(_buffer, ret, "read data:");
117 120 char *vis = malloc(ret*4+1);
118 121 strvisx(vis, _buffer, ret, VIS_WHITE);
119 122 DEBUG(@"read data: %s", vis);
@@ -158,10 +161,6 @@ - (int)flush
158 161 iov[i].iov_len = buf.left;
159 162 tot += buf.left;
160 163 i++;
161   -
162   -#ifndef NO_DEBUG
163   - hexdump(buf.ptr, buf.left, "enqueueing buffer:");
164   -#endif
165 164 }
166 165
167 166 if (tot == 0) {
@@ -391,6 +390,109 @@ - (id)initWithTask:(NSTask *)task
391 390 priority:5];
392 391 }
393 392
  393 +- (id)initWithNode:(NSString *)node
  394 + service:(NSString *)service
  395 + type:(int)socktype
  396 + family:(int)family
  397 + protocol:(int)proto
  398 + error:(NSError **)outError
  399 +{
  400 + struct sockaddr_un addr;
  401 + struct addrinfo hints;
  402 + struct addrinfo *ai, *ai0;
  403 + int res, fd;
  404 +
  405 + if (family == AF_UNSPEC && [node hasPrefix:@"/"]) {
  406 + family = AF_UNIX;
  407 + }
  408 +
  409 + if (family == AF_UNIX) {
  410 + memset(&addr, 0, sizeof(addr));
  411 + addr.sun_family = AF_UNIX;
  412 + if (strlcpy(addr.sun_path, [node UTF8String], sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) {
  413 + if (outError) {
  414 + *outError = [ViError errorWithFormat:@"Path truncated."];
  415 + }
  416 + [self release];
  417 + return nil;
  418 + }
  419 + fd = socket(family, socktype, proto);
  420 + if (fd >= 0 && connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
  421 + close(fd);
  422 + fd = -1;
  423 + }
  424 + } else {
  425 + memset(&hints, 0, sizeof(hints));
  426 + hints.ai_family = family;
  427 + hints.ai_socktype = socktype;
  428 + hints.ai_protocol = proto;
  429 +
  430 + /* This does blocking DNS resolving. */
  431 + res = getaddrinfo([node UTF8String], [service UTF8String], &hints, &ai0);
  432 + if (res != 0) {
  433 + if (outError) {
  434 + *outError = [ViError errorWithFormat:@"%@", gai_strerror(res)];
  435 + }
  436 + [self release];
  437 + return nil;
  438 + }
  439 +
  440 + for (ai = ai0; ai; ai = ai->ai_next) {
  441 + fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
  442 + if (fd < 0) {
  443 + continue;
  444 + }
  445 + if (connect(fd, ai->ai_addr, ai->ai_addrlen) < 0) {
  446 + close(fd);
  447 + fd = -1;
  448 + continue;
  449 + }
  450 + break;
  451 + }
  452 + freeaddrinfo(ai0);
  453 + }
  454 +
  455 + if (fd < 0) {
  456 + if (outError) {
  457 + *outError = [ViError errorWithFormat:@"Failed to connect to %@:%@: %@", node, service, strerror(errno)];
  458 + }
  459 + [self release];
  460 + return nil;
  461 + }
  462 +
  463 + return [self initWithReadDescriptor:fd writeDescriptor:fd priority:5];
  464 +}
  465 +
  466 +- (id)initWithHost:(NSString *)host port:(int)port
  467 +{
  468 + return [self initWithNode:host
  469 + service:[NSString stringWithFormat:@"%i", port]
  470 + type:SOCK_STREAM
  471 + family:0
  472 + protocol:0
  473 + error:nil];
  474 +}
  475 +
  476 ++ (id)streamWithHost:(NSString *)host port:(int)port
  477 +{
  478 + return [[[self alloc] initWithHost:host port:port] autorelease];
  479 +}
  480 +
  481 +- (id)initWithLocalSocket:(NSString *)file
  482 +{
  483 + return [self initWithNode:file
  484 + service:nil
  485 + type:SOCK_STREAM
  486 + family:AF_UNIX
  487 + protocol:0
  488 + error:nil];
  489 +}
  490 +
  491 ++ (id)streamWithLocalSocket:(NSString *)file
  492 +{
  493 + return [[[self alloc] initWithLocalSocket:file] autorelease];
  494 +}
  495 +
394 496 - (void)open
395 497 {
396 498 INFO(@"%s", "open?");
@@ -453,6 +555,11 @@ - (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode
453 555 CFRunLoopAddSource([aRunLoop getCFRunLoop], _outputSource, (CFStringRef)mode);
454 556 }
455 557
  558 +- (void)schedule
  559 +{
  560 + [self scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
  561 +}
  562 +
456 563 - (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode
457 564 {
458 565 DEBUG(@"removing from mode %@", mode);
@@ -510,6 +617,11 @@ - (void)writeData:(NSData *)aData
510 617 }
511 618 }
512 619
  620 +- (void)writeString:(NSString *)aString
  621 +{
  622 + [self writeData:[aString dataUsingEncoding:NSUTF8StringEncoding]];
  623 +}
  624 +
513 625 - (id)propertyForKey:(NSString *)key
514 626 {
515 627 DEBUG(@"key is %@", key);

0 comments on commit b956e99

Please sign in to comment.
Something went wrong with that request. Please try again.