~ubuntu-branches/ubuntu/hardy/texmacs/hardy

« back to all changes in this revision

Viewing changes to src/System/Link/socket_link.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ralf Treinen
  • Date: 2004-04-19 20:34:00 UTC
  • Revision ID: james.westby@ubuntu.com-20040419203400-g4e34ih0315wcn8v
Tags: upstream-1.0.3-R2
ImportĀ upstreamĀ versionĀ 1.0.3-R2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/******************************************************************************
 
3
* MODULE     : socket_link.cpp
 
4
* DESCRIPTION: TeXmacs links by sockets
 
5
* COPYRIGHT  : (C) 2003  Joris van der Hoeven
 
6
*******************************************************************************
 
7
* This software falls under the GNU general public license and comes WITHOUT
 
8
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
 
9
* If you don't have this file, write to the Free Software Foundation, Inc.,
 
10
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
11
******************************************************************************/
 
12
 
 
13
#include "socket_link.hpp"
 
14
#include "sys_utils.hpp"
 
15
#include "hashset.hpp"
 
16
#include "iterator.hpp"
 
17
#include "timer.hpp"
 
18
#include <stdio.h>
 
19
#include <string.h>
 
20
#include <unistd.h>
 
21
#include <fcntl.h>
 
22
#include <sys/wait.h>
 
23
#include <sys/types.h>
 
24
#include <sys/socket.h>
 
25
#include <netinet/in.h>
 
26
#include <netdb.h>
 
27
#include <errno.h>
 
28
 
 
29
hashset<pointer> socket_link_set;
 
30
 
 
31
/******************************************************************************
 
32
* Constructors and destructors for socket_links
 
33
******************************************************************************/
 
34
 
 
35
socket_link_rep::socket_link_rep (string host2, int port2):
 
36
  host (host2), port (port2)
 
37
{
 
38
  socket_link_set->insert ((pointer) this);
 
39
  io     = -1;
 
40
  outbuf = "";
 
41
  alive  = false;
 
42
}
 
43
 
 
44
socket_link_rep::~socket_link_rep () {
 
45
  stop ();
 
46
  socket_link_set->remove ((pointer) this);
 
47
}
 
48
 
 
49
tm_link
 
50
make_socket_link (string host, int port) {
 
51
  return new socket_link_rep (host, port);
 
52
}
 
53
 
 
54
/******************************************************************************
 
55
* Routines for socket_links
 
56
******************************************************************************/
 
57
#define TERMCHAR '\1'
 
58
 
 
59
string
 
60
socket_link_rep::start () {
 
61
  if (alive) return "busy";
 
62
  if (DEBUG_AUTO)
 
63
    cout << "TeXmacs] Connecting to '" << host << ":" << port << "'\n";
 
64
  
 
65
  // getting host
 
66
  char* _host= as_charp (host);
 
67
  struct hostent *hp = gethostbyname (_host);
 
68
  delete[] _host;
 
69
  if (hp == NULL) return "Error: no connection for '" * host * "'";
 
70
 
 
71
  // creating socket
 
72
  io= socket (AF_INET, SOCK_STREAM, 0);
 
73
  if (io < 0) return "Error: socket could not be created";
 
74
 
 
75
  // connecting to socket
 
76
  struct sockaddr_in insock;
 
77
  string where= host * ":" * as_string (port);
 
78
  memset ((char*) &insock, 0, sizeof (insock));
 
79
  insock.sin_family = AF_INET;
 
80
  insock.sin_port = htons ((unsigned short) port);
 
81
  memcpy ((char*) &insock.sin_addr, hp->h_addr, hp->h_length);
 
82
  if (connect (io, (struct sockaddr*) &insock, sizeof (insock)) < 0)
 
83
    return "Error: refused connection to '" * where * "'";
 
84
 
 
85
  // testing whether it works
 
86
  int flags = O_NONBLOCK;
 
87
  if (fcntl (io, F_SETFL, flags) < 0)
 
88
    return "Error: non working connection to '" * where * "'";
 
89
  alive= true;
 
90
  return "ok";
 
91
}
 
92
 
 
93
static string
 
94
debug_io_string (string s) {
 
95
  int i, n= N(s);
 
96
  string r;
 
97
  for (i=0; i<n; i++) {
 
98
    unsigned char c= (unsigned char) s[i];
 
99
    if (c == DATA_BEGIN) r << "[BEGIN]";
 
100
    else if (c == DATA_END) r << "[END]";
 
101
    else if (c == DATA_COMMAND) r << "[COMMAND]";
 
102
    else if (c == DATA_ESCAPE) r << "[ESCAPE]";
 
103
    else r << s[i];
 
104
  }
 
105
  return r;
 
106
}
 
107
 
 
108
void
 
109
socket_link_rep::write (string s, int channel) {
 
110
  if ((!alive) || (channel != LINK_IN)) return;
 
111
  if (DEBUG_IO) cout << "---> " << debug_io_string (s) << "\n";
 
112
  char* _s= as_charp (s);
 
113
  ::write (io, _s, N(s));
 
114
  delete[] _s;
 
115
}
 
116
 
 
117
void
 
118
socket_link_rep::feed (int channel) {
 
119
  if ((!alive) || (channel != LINK_OUT)) return;
 
120
 
 
121
  int r;
 
122
  char tempout[1024];
 
123
  r = ::read (io, tempout, 1024);
 
124
  if (r == ERROR) {
 
125
    cerr << "TeXmacs] read failed from#'" << host << ":" << port << "'\n";
 
126
    wait (NULL);
 
127
  }
 
128
  else if (r != 0) {
 
129
    if (DEBUG_IO) cout << debug_io_string (string (tempout, r));
 
130
    outbuf << string (tempout, r);
 
131
  }
 
132
}
 
133
 
 
134
string
 
135
socket_link_rep::read (int channel) {
 
136
  if (channel == LINK_OUT) {
 
137
    string r= outbuf;
 
138
    outbuf= "";
 
139
    return r;
 
140
  }
 
141
  else return "";
 
142
}
 
143
 
 
144
void
 
145
socket_link_rep::listen (int msecs) {
 
146
  int wait_until= texmacs_time () + msecs;
 
147
  while (outbuf == "") {
 
148
    listen_to_sockets (); // FIXME: should listen more specifically
 
149
    if (texmacs_time () > wait_until) break;
 
150
  }
 
151
}
 
152
 
 
153
void
 
154
socket_link_rep::interrupt () {
 
155
}
 
156
 
 
157
void
 
158
socket_link_rep::stop () {
 
159
  if (!alive) return;
 
160
  alive= false;
 
161
  close (io);
 
162
  wait (NULL);
 
163
}
 
164
 
 
165
/******************************************************************************
 
166
* Listen to all active sockets (may be optimized for speed)
 
167
******************************************************************************/
 
168
 
 
169
void
 
170
listen_to_sockets () {
 
171
  while (true) {
 
172
    fd_set rfds;
 
173
    FD_ZERO (&rfds);
 
174
    int max_fd= 0;
 
175
    iterator<pointer> it= iterate (socket_link_set);
 
176
    while (it->busy()) {
 
177
      socket_link_rep* con= (socket_link_rep*) it->next();
 
178
      if (con->alive) {
 
179
        FD_SET (con->io, &rfds);
 
180
        if (con->io >= max_fd) max_fd= con->io+1;
 
181
      }
 
182
    }
 
183
    if (max_fd == 0) break;
 
184
 
 
185
    struct timeval tv;
 
186
    tv.tv_sec  = 0;
 
187
    tv.tv_usec = 0;
 
188
    int nr= select (max_fd, &rfds, NULL, NULL, &tv);
 
189
    if (nr==0) break;
 
190
 
 
191
    it= iterate (socket_link_set);
 
192
    while (it->busy()) {
 
193
      socket_link_rep* con= (socket_link_rep*) it->next();
 
194
      if (con->alive && FD_ISSET (con->io, &rfds)) con->feed (LINK_OUT);
 
195
    }
 
196
  }
 
197
}
 
198
 
 
199
/******************************************************************************
 
200
* Emergency exit for all sockets
 
201
******************************************************************************/
 
202
 
 
203
void
 
204
close_all_sockets () {
 
205
  iterator<pointer> it= iterate (socket_link_set);
 
206
  while (it->busy()) {
 
207
    socket_link_rep* con= (socket_link_rep*) it->next();
 
208
    if (con->alive) {
 
209
      close (con->io);
 
210
      con->alive= false;
 
211
    }
 
212
  }
 
213
}