Edinburgh Speech Tools  2.4-release
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
filetrans.cc
1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1996 */
6 /* All Rights Reserved. */
7 /* */
8 /* Permission is hereby granted, free of charge, to use and distribute */
9 /* this software and its documentation without restriction, including */
10 /* without limitation the rights to use, copy, modify, merge, publish, */
11 /* distribute, sublicense, and/or sell copies of this work, and to */
12 /* permit persons to whom this work is furnished to do so, subject to */
13 /* the following conditions: */
14 /* 1. The code must retain the above copyright notice, this list of */
15 /* conditions and the following disclaimer. */
16 /* 2. Any modifications must be clearly marked as such. */
17 /* 3. Original authors' names are not deleted. */
18 /* 4. The authors' names are not used to endorse or promote products */
19 /* derived from this software without specific prior written */
20 /* permission. */
21 /* */
22 /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25 /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30 /* THIS SOFTWARE. */
31 /* */
32 /*************************************************************************/
33 /* Author : Alan Black */
34 /* Date : December 1996 */
35 /*-----------------------------------------------------------------------*/
36 /* */
37 /* File transfer over open file descriptors. Uses key stuffing */
38 /* to allow transfer of any file over an open link (usually a socket) */
39 /* */
40 /*=======================================================================*/
41 #include "EST_unix.h"
42 #include <cstdio>
43 #include "EST_String.h"
44 #include "EST_io_aux.h"
45 
46 // The following key is used when stuffing files down a socket.
47 // This key in when received denotes the end of file. Any occurrence
48 // of key in the file with have X inserted in it, and the receiving end
49 // with remove that X in the file. This is a technique I learned from
50 // HDLC network protocols which guarantees 0x7e (6 bits) starts a header.
51 // This allows transfer of files even if they include the stuff key.
52 const char *file_stuff_key = "ft_StUfF_key";
53 
54 static int getc_unbuffered(SOCKET_FD fd)
55 {
56  // An attempted to get rid of the buffering
57  char c;
58  int n;
59 
60 #ifdef WIN32
61  n = recv(fd,&c,1,0);
62 #else
63  n = read(fd,&c,1);
64 #endif
65 
66  if (n == 0) // this isn't necessarily eof
67  return EOF;
68  else
69  return c; // and this might be -1 (EOF)
70 }
71 
72 int socket_receive_file(SOCKET_FD fd,const EST_String &filename)
73 {
74  // Copy the file from fd to filename using the 7E stuff key
75  // mechanism so binary files may pass through the socket
76  // without signals or eof.
77  FILE *outfd;
78  int k,i,c;
79 
80  if ((outfd=fopen(filename,"wb")) == NULL)
81  {
82  cerr << "socket_receive_file: can't find file \"" <<
83  filename << "\"\n";
84  return -1;
85  }
86 
87  k=0;
88  while (file_stuff_key[k] != '\0')
89  {
90  c = getc_unbuffered(fd);
91  if (file_stuff_key[k] == c)
92  k++;
93  else if ((c == 'X') && (file_stuff_key[k+1] == '\0'))
94  {
95  for (i=0; i < k; i++) putc(file_stuff_key[i],outfd);
96  k=0;
97  // omit the stuffed 'X'
98  }
99  else
100  {
101  for (i=0; i < k; i++) putc(file_stuff_key[i],outfd);
102  k=0;
103  putc(c,outfd);
104  }
105  }
106  fclose(outfd);
107  return 0;
108 }
109 
110 int socket_send_file(SOCKET_FD fd,const EST_String &filename)
111 {
112  // Send file down fd using the 7E end stuffing technique.
113  // This guarantees the binary transfer without any other
114  // signals eof etc
115 #ifndef WIN32
116  FILE *ffd = fdopen(dup(fd),"wb"); // use some buffering
117 #endif
118  FILE *infd;
119  int k,c;
120 
121  if ((infd=fopen(filename,"rb")) == NULL)
122  {
123  cerr << "socket_send_file: can't find file \"" <<
124  filename << "\"\n";
125  return -1;
126  }
127 
128  k=0;
129  while ((c=getc(infd)) != EOF)
130  {
131  if (file_stuff_key[k] == c)
132  k++;
133  else
134  k=0;
135  if (file_stuff_key[k] == '\0')
136  {
137 #ifdef WIN32
138  const char filler='X';
139  send(fd,&filler,1,0);
140 #else
141  putc('X',ffd); // stuff filler
142 #endif
143  k=0;
144  }
145 #ifdef WIN32
146  send(fd,(const char *)&c,1,0);
147 #else
148  putc(c,ffd);
149 #endif
150  }
151  for (k=0; file_stuff_key[k] != '\0'; k++)
152 #ifdef WIN32
153  send(fd,file_stuff_key+k,1,0);
154 #else
155  putc(file_stuff_key[k],ffd); // stuff whole key as its the end
156 
157  fflush(ffd);
158  fclose(ffd);
159 #endif
160  fclose(infd);
161  return 0;
162 }