~ubuntu-branches/ubuntu/raring/voxbo/raring

« back to all changes in this revision

Viewing changes to lib/connect.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Hanke
  • Date: 2010-06-06 11:33:11 UTC
  • Revision ID: james.westby@ubuntu.com-20100606113311-v3c13imdkkd5n7ae
Tags: upstream-1.8.5~svn1172
ImportĀ upstreamĀ versionĀ 1.8.5~svn1172

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
// connect.cpp
 
3
// safe, easy connection-related functions for VoxBo and beyond!
 
4
// Copyright (c) 1998-2008 by The VoxBo Development Team
 
5
 
 
6
// This file is part of VoxBo
 
7
// 
 
8
// VoxBo is free software: you can redistribute it and/or modify it
 
9
// under the terms of the GNU General Public License as published by
 
10
// the Free Software Foundation, either version 3 of the License, or
 
11
// (at your option) any later version.
 
12
// 
 
13
// VoxBo is distributed in the hope that it will be useful, but
 
14
// WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
// General Public License for more details.
 
17
// 
 
18
// You should have received a copy of the GNU General Public License
 
19
// along with VoxBo.  If not, see <http://www.gnu.org/licenses/>.
 
20
// 
 
21
// For general information on VoxBo, including the latest complete
 
22
// source code and binary distributions, manual, and associated files,
 
23
// see the VoxBo home page at: http://www.voxbo.org/
 
24
//
 
25
// original version written by Dan Kimberg
 
26
 
 
27
using namespace std;
 
28
 
 
29
#include <sys/time.h>
 
30
#include <unistd.h>
 
31
#include <fcntl.h>
 
32
#include <sys/types.h>
 
33
#include <sys/stat.h>
 
34
#include <sys/socket.h>
 
35
#include <netinet/in.h>
 
36
#include <math.h>
 
37
#include <errno.h>
 
38
#include <sys/un.h>
 
39
#include "vbutil.h"
 
40
 
 
41
// buffer size for send/receive file
 
42
#define F_BUFSIZE 65536
 
43
 
 
44
int
 
45
safe_recv(int sock,char *buf,int len,float secs)
 
46
{
 
47
  fd_set ff;
 
48
  struct timeval t_start,t_deadline,t_current,t_timeout;
 
49
  int pos=0,err;
 
50
 
 
51
  // buf is valid even if we fail utterly
 
52
  buf[0]='\0';
 
53
  // before we do anything time-consuming, set a deadline
 
54
  gettimeofday(&t_start,NULL);
 
55
  t_deadline.tv_sec = (int)secs;
 
56
  t_deadline.tv_usec = lround(((secs - floor(secs))*1000000.0));
 
57
  t_deadline=t_start+t_deadline;
 
58
 
 
59
  while(1) {
 
60
    // create socket mask for just the one socket
 
61
    FD_ZERO(&ff);
 
62
    FD_SET(sock,&ff);
 
63
    // timeout as specified
 
64
    gettimeofday(&t_current,NULL);
 
65
    t_timeout=t_deadline-t_current;
 
66
    // make sure there's data available
 
67
    err = select(sock+1,&ff,NULL,NULL,&t_timeout);
 
68
    if (err < 1)
 
69
      return err;
 
70
    err=recv(sock,buf+pos,len-pos,0);
 
71
    // break if we didn't get anything before the deadline
 
72
    // buf[pos+err]='\0';  // FIXME
 
73
    if (err<=0) {
 
74
      break;
 
75
      if (errno==EAGAIN)  // FIXME not needed now that we're nonblocking
 
76
        continue;
 
77
      else
 
78
        break;
 
79
    }
 
80
    pos+=err;
 
81
    // break if we got something EOT-terminated
 
82
    if (buf[pos-1]=='\0')
 
83
      break;
 
84
    // break if we filled the buffer
 
85
    if (pos>=len)
 
86
      break;
 
87
  }
 
88
  // null-terminate if there's room, in case someone lazy uses it as a string
 
89
  if (pos > 0 && pos<len)
 
90
    buf[pos]='\0';
 
91
  return pos;
 
92
}
 
93
 
 
94
int
 
95
safe_send(int sock,char *buf,int len,float secs)
 
96
{
 
97
// safe_send() just makes sure the socket is writeable before we send.
 
98
// at present it does not try to break the message up into pieces if
 
99
// it's too big.  so whoever calls safe_send should be careful of
 
100
// that.
 
101
 
 
102
  fd_set ff;
 
103
  struct timeval t_start,t_deadline,t_current,t_timeout;
 
104
  int err;
 
105
 
 
106
  // before we do anything time-consuming, set a deadline
 
107
  gettimeofday(&t_start,NULL);
 
108
  t_deadline.tv_sec = (int)secs;
 
109
  t_deadline.tv_usec = lround(((secs - floor(secs))*1000000.0));
 
110
  t_deadline=t_start+t_deadline;
 
111
 
 
112
  // create socket mask for just the one socket
 
113
  FD_ZERO(&ff);
 
114
  FD_SET(sock,&ff);
 
115
  // timeout as specified
 
116
  gettimeofday(&t_current,NULL);
 
117
  t_timeout=t_deadline-t_current;
 
118
  // make sure we can send
 
119
  err = select(sock+1,NULL,&ff,NULL,&t_timeout);
 
120
  if (err < 1)
 
121
    return err;
 
122
  err=send(sock,buf,len,0);
 
123
  if (err!=len)
 
124
    return 101;
 
125
  else
 
126
    return 0;
 
127
}
 
128
 
 
129
int
 
130
safe_connect(struct sockaddr_in *addr,float secs)
 
131
{
 
132
  return safe_connect((struct sockaddr *)addr,secs);
 
133
}
 
134
 
 
135
int
 
136
safe_connect(struct sockaddr_un *addr,float secs)
 
137
{
 
138
  return safe_connect((struct sockaddr *)addr,secs);
 
139
}
 
140
 
 
141
int
 
142
safe_connect(struct sockaddr *addr,float secs)
 
143
{
 
144
// safe_connect() is a version of connect that will timeout after a
 
145
// given deadline.  to do this correctly, we put the socket in
 
146
// nonblocking mode first, call connect, and if connect doesn't fail
 
147
// immediately, we're either connected or in EINPROGRESS.  if the
 
148
// latter, we can use getsockopt to see if there's an error.  see
 
149
// http://www.lcg.org/sock-faq/connect.c for some details.
 
150
// (non-blocking send/recv is a lot easier.  just use select() with a
 
151
// timeout to make sure the socket is ready to read/write.)
 
152
 
 
153
  int err,s,sz;
 
154
  fd_set ff;
 
155
  struct timeval tv;
 
156
 
 
157
  s = socket(addr->sa_family,SOCK_STREAM,0);
 
158
  if (s == -1)
 
159
    return (-1);
 
160
 
 
161
  fcntl(s,F_SETFL,O_NONBLOCK);
 
162
 
 
163
  if (addr->sa_family==AF_INET)
 
164
    sz=sizeof(struct sockaddr_in);
 
165
  else
 
166
    sz=sizeof(struct sockaddr_un);
 
167
  err = connect(s,addr,sz);
 
168
  if (err && (errno != EINPROGRESS)) {
 
169
    close(s);
 
170
    return(-2);
 
171
  }
 
172
  // set up for select()
 
173
  FD_ZERO(&ff);
 
174
  FD_SET(s,&ff);
 
175
  tv.tv_sec = (int)secs;
 
176
  tv.tv_usec = lround(((secs - floor(secs))*1000000.0));
 
177
 
 
178
  // wait until socket is writeable
 
179
  err = select(s+1,NULL,&ff,NULL,&tv);
 
180
  if (err < 1) {
 
181
    close(s);
 
182
    return (-3);
 
183
  }
 
184
  socklen_t len=sizeof(int);
 
185
  if (getsockopt(s,SOL_SOCKET,SO_ERROR,&err,&len) == -1) {
 
186
    close(s);
 
187
    return (-4);
 
188
  }
 
189
  return s;
 
190
}
 
191
 
 
192
int
 
193
send_file(int s,string fname)
 
194
{
 
195
// send_file() tries to send a file through a socket.  it's presumed
 
196
// that the process on the other end of the socket is already
 
197
// expecting a file to be sent (i.e., is calling receive_file).
 
198
 
 
199
  struct stat st;
 
200
  FILE *fp=fopen(fname.c_str(),"r");
 
201
  if (!fp)
 
202
    return 101;
 
203
  if (fstat(fileno(fp),&st)) {
 
204
    fclose(fp);
 
205
    return 111;
 
206
  }
 
207
 
 
208
  int filesize=st.st_size;
 
209
  char buf[F_BUFSIZE];
 
210
  // send filename
 
211
  sprintf(buf,"send %s %d",fname.c_str(),filesize);
 
212
  if (safe_send(s,buf,strlen(buf)+1,10.0)) {
 
213
    fclose(fp);
 
214
    return 102;
 
215
  }
 
216
 
 
217
  int bytestosend=filesize;
 
218
  int packetsize;
 
219
  while(bytestosend>0) {
 
220
    packetsize=(F_BUFSIZE>bytestosend?bytestosend:F_BUFSIZE);
 
221
    // read a chunk
 
222
    fread(buf,1,packetsize,fp);
 
223
    // send it
 
224
    if (safe_send(s,buf,packetsize,10.0)) {
 
225
      fclose(fp);
 
226
      return 103;
 
227
    }
 
228
    bytestosend-=packetsize;
 
229
  }
 
230
  if (safe_recv(s,buf,F_BUFSIZE,10.0)<0)
 
231
    return 55;
 
232
  buf[4]='\0';
 
233
  if ((string)buf=="ACK")
 
234
    return 0;
 
235
  else return 66;
 
236
}
 
237
 
 
238
int
 
239
receive_file(int s,string fname,int filesize)
 
240
{
 
241
  FILE *fp=fopen(fname.c_str(),"w");
 
242
  if (!fp)
 
243
    return 101;
 
244
  char buf[F_BUFSIZE];
 
245
 
 
246
  int packetsize,cnt=0,total=0;
 
247
  while(1) {
 
248
    // read a chunk
 
249
    if ((cnt=safe_recv(s,buf,F_BUFSIZE,10.0))<0) {
 
250
      fclose(fp);
 
251
      return 103;
 
252
    }
 
253
    // write it
 
254
    cnt=fwrite(buf,1,cnt,fp);
 
255
    total+=cnt;
 
256
  }
 
257
  fclose(fp);
 
258
  if (total!=filesize)
 
259
    return 103;
 
260
  if (safe_send(s,buf,packetsize,10.0)) {
 
261
    fclose(fp);
 
262
    return 105;
 
263
  }
 
264
  return 0;
 
265
}
 
266