1 // daemon/Session.cc
2 // This file is part of Anyterm; see http://anyterm.org/
3 // (C) 2005-2006 Philip Endecott
4
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19
20 #include "Session.hh"
21
22 #include <sstream>
23 #include <iomanip>
24
25 #include <unistd.h>
26 #include <signal.h>
27
28 #include <boost/bind.hpp>
29
30 #include "Lock.hh"
31
32 #include "config.hh"
33 #include "html.hh"
34 #include "editscript.hh"
35 #include "Error.hh"
36 #include "Iconver.hh"
37 #include "unicode.hh"
38
39
40 using namespace std;
41 using namespace pbe;
42
43
Session(int r,int c,int sb,string host,string user,string param,int t,activityfactory_t af,string charset_,bool diff_)44 Session::Session(int r, int c, int sb,
45 string host, string user, string param,
46 int t,
47 activityfactory_t af,
48 string charset_,
49 bool diff_):
50 rows(r),
51 cols(c),
52 scrollback(sb),
53 time_out(t),
54 charset(charset_),
55 diff(diff_),
56 utf8_to_charset("UTF-8",charset),
57 charset_to_ucs4(charset,UCS4_NATIVE),
58 ucs4_to_utf8(UCS4_NATIVE,"UTF-8"),
59 screen(rows,cols,scrollback),
60 error(false),
61 term(rows,cols,screen),
62 activity(af(boost::bind(&Session::process_output,this,_1),
63 boost::bind(&Session::process_error,this,_1),
64 host, user, param, r, c))
65 {
66 dirty=true;
67 touch();
68 }
69
70
~Session()71 Session::~Session()
72 {}
73
74
75 // Timeout unused sessions:
76
touch(void)77 void Session::touch(void)
78 {
79 last_access = time(NULL);
80 }
81
82
83 // Check if session has a backend error to report
84
report_any_backend_error(void)85 void Session::report_any_backend_error(void)
86 {
87 if (error) {
88 error=false;
89 throw Error(error_msg);
90 }
91 }
92
93
94 // Handle Apache requests:
95
int_to_string(int i)96 string int_to_string(int i)
97 {
98 char b[32];
99 snprintf(b,sizeof(b),"%d",i);
100 return b;
101 }
102
103
send(string k)104 void Session::send(string k)
105 {
106 if (!k.empty()) {
107 string dk = utf8_to_charset(k);
108 activity->send(dk);
109 }
110
111 touch();
112 }
113
114
115
escape_html(string s)116 string escape_html(string s)
117 {
118 string t;
119 for(string::size_type i=0; i<s.length(); i++) {
120 char c=s[i];
121 switch(c) {
122 case '<': t+="<"; break;
123 case '>': t+=">"; break;
124 case '&': t+="&"; break;
125 default: t+=c; break;
126 }
127 }
128 return t;
129 }
130
131
rcv(void)132 string Session::rcv(void)
133 {
134 {
135 Lock<screen_lock_t> l(screen_lock);
136 if (!dirty && !error) {
137 dirty_condition.timed_wait(l,10.0F);
138 }
139 }
140 touch();
141
142 report_any_backend_error();
143
144 bool was_dirty;
145 ucs4_string html_screen;
146 {
147 Lock<screen_lock_t> l(screen_lock);
148 was_dirty = dirty;
149 dirty=false;
150 if (!was_dirty) {
151 return "n";
152 }
153 html_screen = htmlify_screen(screen);
154 }
155
156 string utf8_editscript;
157 if (diff) {
158 ucs4_string editscript = make_editscript(old_html_screen,html_screen);
159 old_html_screen=html_screen;
160 utf8_editscript = ucs4_to_utf8(editscript);
161 } else {
162 utf8_editscript = "R";
163 utf8_editscript.append(ucs4_to_utf8(html_screen));
164 }
165
166 return utf8_editscript;
167 }
168
169
process_output(string s)170 void Session::process_output(string s)
171 {
172 ucs4_string ucs4_s = charset_to_ucs4(s);
173 {
174 Lock<screen_lock_t> l(screen_lock);
175 term.write(ucs4_s);
176 dirty = true;
177 }
178 dirty_condition.notify_all();
179 }
180
181
process_error(string s)182 void Session::process_error(string s)
183 {
184 // We could have a lock here, but maybe we can trust that the assignment
185 // to error is atomic.
186 error_msg = s;
187 error = true;
188 dirty_condition.notify_all();
189 }
190
191
timed_out(void)192 bool Session::timed_out(void)
193 {
194 return time(NULL) - last_access > time_out;
195 }
196
197