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
******************************************************************************/
13
#include "socket_link.hpp"
14
#include "sys_utils.hpp"
15
#include "hashset.hpp"
16
#include "iterator.hpp"
23
#include <sys/types.h>
24
#include <sys/socket.h>
25
#include <netinet/in.h>
29
hashset<pointer> socket_link_set;
31
/******************************************************************************
32
* Constructors and destructors for socket_links
33
******************************************************************************/
35
socket_link_rep::socket_link_rep (string host2, int port2):
36
host (host2), port (port2)
38
socket_link_set->insert ((pointer) this);
44
socket_link_rep::~socket_link_rep () {
46
socket_link_set->remove ((pointer) this);
50
make_socket_link (string host, int port) {
51
return new socket_link_rep (host, port);
54
/******************************************************************************
55
* Routines for socket_links
56
******************************************************************************/
60
socket_link_rep::start () {
61
if (alive) return "busy";
63
cout << "TeXmacs] Connecting to '" << host << ":" << port << "'\n";
66
char* _host= as_charp (host);
67
struct hostent *hp = gethostbyname (_host);
69
if (hp == NULL) return "Error: no connection for '" * host * "'";
72
io= socket (AF_INET, SOCK_STREAM, 0);
73
if (io < 0) return "Error: socket could not be created";
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 * "'";
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 * "'";
94
debug_io_string (string s) {
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]";
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));
118
socket_link_rep::feed (int channel) {
119
if ((!alive) || (channel != LINK_OUT)) return;
123
r = ::read (io, tempout, 1024);
125
cerr << "TeXmacs] read failed from#'" << host << ":" << port << "'\n";
129
if (DEBUG_IO) cout << debug_io_string (string (tempout, r));
130
outbuf << string (tempout, r);
135
socket_link_rep::read (int channel) {
136
if (channel == LINK_OUT) {
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;
154
socket_link_rep::interrupt () {
158
socket_link_rep::stop () {
165
/******************************************************************************
166
* Listen to all active sockets (may be optimized for speed)
167
******************************************************************************/
170
listen_to_sockets () {
175
iterator<pointer> it= iterate (socket_link_set);
177
socket_link_rep* con= (socket_link_rep*) it->next();
179
FD_SET (con->io, &rfds);
180
if (con->io >= max_fd) max_fd= con->io+1;
183
if (max_fd == 0) break;
188
int nr= select (max_fd, &rfds, NULL, NULL, &tv);
191
it= iterate (socket_link_set);
193
socket_link_rep* con= (socket_link_rep*) it->next();
194
if (con->alive && FD_ISSET (con->io, &rfds)) con->feed (LINK_OUT);
199
/******************************************************************************
200
* Emergency exit for all sockets
201
******************************************************************************/
204
close_all_sockets () {
205
iterator<pointer> it= iterate (socket_link_set);
207
socket_link_rep* con= (socket_link_rep*) it->next();