Statistics
| Branch: | Tag: | Revision:

dvbd / src / unixclientsocket.cpp @ ac92ede7

History | View | Annotate | Download (3.94 KB)

1
/*
2
  Copyright 2003 John Knottenbelt
3
  
4
  This program is free software; you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation; either version 2 of the License, or
7
  (at your option) any later version.
8
 
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
 
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17
*/
18

    
19
#include "unixclientsocket.h"
20
#include "inputbuffer.h"
21
#include "outputbuffer.h"
22
#include "utils.h"
23

    
24
#include <iostream>
25
#include <cstring>
26
#include <cstdlib>
27
#include <cerrno>
28
#include <unistd.h>
29
#include <sys/types.h>
30
#include <sys/socket.h>
31
#include <sys/un.h>
32
#include <fcntl.h>
33

    
34
UnixClientSocket::UnixClientSocket(const std::string &path)
35
  : fd(-1), blocking(true), overflowed(false), input(NULL), output(NULL)
36
{
37
  connect(path);
38
}
39

    
40
UnixClientSocket::~UnixClientSocket()
41
{
42
  if (fd != -1) {
43
    close(fd);
44
    delete input;
45
    delete output;
46
  }
47
}
48

    
49
bool UnixClientSocket::connect(const std::string &path)
50
{
51
  fd = socket(PF_UNIX, SOCK_STREAM, 0);
52

    
53
  if (fd < 0) {
54
    std::cerr << "Fatal error: failed to create socket for connecting:\n"
55
              << strerror(errno) << std::endl;
56
    return false;
57
  }
58

    
59
  struct sockaddr_un addr;
60
  addr.sun_family = AF_UNIX;
61
  strcpy(addr.sun_path, path.c_str());
62

    
63
  if (::connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
64
    close(fd);
65
    fd = -1;
66
    return false;
67
  }
68

    
69
  setNonBlocking(fd);
70

    
71
  input = new InputBuffer(fd, 8192, 32768);
72
  output = new OutputBuffer(fd, 8192, 32768);
73
  return true;
74
}
75

    
76
UnixClientSocket::operator bool() const
77
{
78
  return fd >= 0 && !overflowed;
79
}
80

    
81
void UnixClientSocket::setBlocking(bool mode)
82
{
83
  blocking = mode;
84
}
85

    
86
bool UnixClientSocket::isBlocking() const
87
{
88
  return blocking;
89
}
90

    
91
bool UnixClientSocket::write(const std::string &data)
92
{
93
  if (!output->write(data))
94
    return false;
95

    
96
  if (blocking)
97
    return output->flush();
98
  else
99
    return true;
100
}
101

    
102
bool UnixClientSocket::getMoreData()
103
{
104
  Select s;
105
  addSelectFDs(s);
106

    
107
  if (!blocking)
108
    s.addAlarm(0, 0);
109

    
110
  s.wait();
111

    
112
  if (!isReady(s))
113
    return false;
114

    
115
  if (!processReady(s))
116
    return false;
117

    
118
  return true;
119
}
120

    
121
int UnixClientSocket::read(char *data, int count)
122
{
123
  if (count > input->getMaxSize())
124
    return -1;
125

    
126
  if (!blocking) {
127
  tryAgain:
128
    if (count < input->getUsed()) 
129
      return input->read(data, count) ? count : -1;
130
    else if (input->getUsed() > 0) {
131
      count = input->getUsed();
132
      return input->read(data, count) ? count : -1;
133
    }
134
    else {
135
      if (getMoreData())
136
        goto tryAgain;
137
      else
138
        return -1;
139
    }
140
  }
141
  else {
142
    // Blocking read of N bytes
143
    while (input->getUsed() < count) {
144
      if (!getMoreData())
145
        return -1;
146
    };
147

    
148
    return input->read(data, count) ? count : - 1;
149
  }
150
}
151

    
152
void UnixClientSocket::addSelectFDs(Select &s) const
153
{
154
  // Write data out before accepting new data
155
  if (output->getUsed() > 0)
156
    output->addSelectFDs(s);
157
  else
158
    input->addSelectFDs(s);
159
}
160

    
161
bool UnixClientSocket::isReady(const Select &s) const
162
{
163
  return input->isReady(s) || output->isReady(s);
164
}
165

    
166
bool UnixClientSocket::processReady(const Select &s) 
167
{
168
  if (output->isReady(s)) {
169
    if (!output->process())
170
      return false;
171
  }
172
  else if (input->isReady(s)) {
173
    if (!input->process())
174
      return false;
175
  }
176
  return true;
177
}
178

    
179
bool UnixClientSocket::readLine(std::string &line)
180
{
181
  if (blocking) {
182
    while (true) {
183
      if (input->readLine(line))
184
        return true;
185

    
186
      if (input->getFree() == 0)
187
        return false;
188
      
189
      if (!getMoreData())
190
        return false;
191
    }
192
  }
193
  else 
194
    return input->readLine(line);
195
}
196

    
197
bool UnixClientSocket::writeCredentials()
198
{
199
  return output->writeCredentials();
200
}