public
Description: My OS X Thermometer client.
Clone URL: git://github.com/dustin/osx-thermometer.git
osx-thermometer / LempClient.m
100644 161 lines (136 sloc) 3.725 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//
// LempClient.m
// Thermometer
// arch-tag: 855E9B81-A4AE-11D8-B81D-000A957659CC
//
// Created by Dustin Sallings on Wed May 12 2004.
// Copyright (c) 2004 Dustin Sallings. All rights reserved.
//
 
#import "LempClient.h"
#import "TempReading.h"
 
@implementation LempClient
 
static int
initSocket(const char *host, int port)
{
    struct hostent *hp;
    int success, i, flag;
    register int s = -1;
    struct linger l;
    struct sockaddr_in sin;
 
    if (host == NULL || port == 0)
        return (-1);
 
    if ((hp = gethostbyname(host)) == NULL) {
#ifdef HAVE_HERROR
        herror("gethostbyname");
#else
        fprintf(stderr, "Error looking up %s\n", host);
#endif
        return (-1);
    }
    success = 0;
 
    /* of course, replace that 1 with the max number of con attempts */
    for (i = 0; i < 1; i++) {
        if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
            perror("socket");
            return (-1);
        }
        sin.sin_family = AF_INET;
        sin.sin_port = htons(port);
        memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
 
        l.l_onoff = 1;
        l.l_linger = 60;
        setsockopt(s, SOL_SOCKET, SO_LINGER, (char *) &l, sizeof(l));
 
        flag = 1;
        if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
            sleep(1);
        } else {
            success = 1;
            break;
        }
    }
 
    if (!success)
        s = -1;
 
    return (s);
}
 
-(NSString *)readLine
{
  char buf[120];
  id rv=nil;
  if(fgets(buf, sizeof(buf), _file) != NULL) {
    rv=[[NSString stringWithCString:buf length:strlen(buf)]
      stringByTrimmingCharactersInSet:
        [NSCharacterSet whitespaceAndNewlineCharacterSet]];
  }
  return(rv);
}
 
-(void)initTherms
{
  NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
  
  NSLog(@"Initializing thermometers");
  NSMutableArray *a=[[NSMutableArray alloc] initWithCapacity:16];
  
  NSString *line=[self readLine];
  while(line != nil && [line hasPrefix: @"221"]) {
    NSArray *parts=[line componentsSeparatedByString: @"\t"];
    NSString *name=[parts objectAtIndex: 1];
    NSLog(@"Got therm ``%@''", name);
    [a addObject: name];
    line=[self readLine];
  }
  
  _therms=[NSArray arrayWithArray: (NSArray *)a];
  [_therms retain];
  
  [a release];
  [pool release];
}
 
-(id)initWithDelegate:(id)d host:(NSString *)hostname port:(int)portnum;
{
  self=[super init];
  
  _fd=initSocket([hostname cString], portnum);
  if (_fd >= 0) {
    _file=fdopen(_fd, "r");
    NSString *firstLine=[self readLine];
    if([firstLine hasPrefix: @"220"]) {
      [self initTherms];
      _delegate=d;
    } else {
      NSLog(@"Error in first line of lemp protocol: %@", firstLine);
      [self release];
      return nil;
    }
  } else {
    [self release];
    return nil;
  }
  
  return self;
}
 
-(NSArray *)therms
{
  return(_therms);
}
 
-(void)readLoop:(id)nothing
{
  BOOL going=YES;
  while(going) {
    NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
    NSString *str=[self readLine];
    // NSLog(@"Loop read %@", str);
    
    if(str == nil) {
      going=NO;
      NSLog(@"LEMP client exiting...");
    } else if([str hasPrefix: @"200"] || [str hasPrefix: @"223"]) {
      NSArray *parts=[str componentsSeparatedByString: @"\t"];
      NSString *name=[parts objectAtIndex: 1];
      float reading=[[parts objectAtIndex: 2] floatValue];
      // NSLog(@"Got reading from %@: %.2f", name, reading);
      TempReading *tr=[[TempReading alloc]
        initWithName:name reading:reading];
      [tr autorelease];
      [_delegate performSelectorOnMainThread:@selector(receiveUpdate:)
        withObject:tr waitUntilDone:NO];
    }
 
    [pool release];
  }
  // Let the listener know we're exiting
  [_delegate performSelectorOnMainThread:@selector(lempExiting:)
    withObject:self waitUntilDone:NO];
}
 
@end