xref: /haiku/src/add-ons/print/transports/lpr/LpsClient.cpp (revision 58481f0f6ef1a61ba07283f012cafbc2ed874ead)
1 // Sun, 18 Jun 2000
2 // Y.Takagi
3 
4 #if defined(__HAIKU__) || defined(HAIKU_TARGET_PLATFORM_BONE)
5 #	include <sys/socket.h>
6 #	include <netdb.h>
7 #else
8 #	include <net/socket.h>
9 #	include <net/netdb.h>
10 #endif
11 
12 #include <errno.h>
13 #include <string.h>
14 
15 #include <iomanip>
16 #include <algorithm>
17 #include "LpsClient.h"
18 #include "Socket.h"
19 //#include "DbgMsg.h"
20 
21 #if (!__MWERKS__)
22 using namespace std;
23 #else
24 #define std
25 #endif
26 
27 #define LPS_SERVER_PORT		515
28 #define LPS_CLIENT_PORT_S	721
29 #define LPS_CLIENT_PORT_E	731
30 
31 #define LPS_CHECK_QUEUE 			'\001'
32 #define LPS_PRINT_JOB				'\002'
33 #define LPS_DISPLAY_SHORT_QUEUE 	'\003'
34 #define LPS_DISPLAY_LONG_QUEUE		'\004'
35 #define LPS_REMOVE_JOB				'\005'
36 #define LPS_END_TRANSFER			'\000'
37 #define LPS_ABORT					'\001'
38 #define LPS_RECEIVE_CONTROL_FILE	'\002'
39 #define LPS_RECEIVE_DATA_FILE		'\003'
40 
41 #define LPS_OK						'\0'
42 #define LPS_ERROR					'\1'
43 #define LPS_NO_SPOOL_SPACE			'\2'
44 
45 #ifndef INADDR_NONE
46 #define INADDR_NONE		0xffffffff
47 #endif
48 
49 #define ERRNO	errno
50 
51 
52 LpsClient::LpsClient(const char *host)
53 	: connected(false), __host(host), __sock(NULL)
54 {
55 }
56 
57 LpsClient::~LpsClient()
58 {
59 	close();
60 }
61 
62 void LpsClient::connect() throw(LPSException)
63 {
64 //	DBGMSG(("connect\n"));
65 
66 	for (int localPort = LPS_CLIENT_PORT_S ; localPort <=  LPS_CLIENT_PORT_E ; localPort++) {
67 		if (__sock) {
68 			delete __sock;
69 		}
70 		__sock = new Socket(__host.c_str(), LPS_SERVER_PORT, localPort);
71 		if (__sock->good()) {
72 			__is = &__sock->getInputStream();
73 			__os = &__sock->getOutputStream();
74 			connected = true;
75 			return;
76 		}
77 	}
78 
79 	throw(LPSException(__sock->getLastError()));
80 }
81 
82 void LpsClient::close()
83 {
84 //	DBGMSG(("close\n"));
85 
86 	connected = false;
87 	if (__sock) {
88 		delete __sock;
89 		__sock = NULL;
90 	}
91 }
92 
93 void LpsClient::receiveJob(const char *printer) throw(LPSException)
94 {
95 //	DBGMSG(("tell_receive_job\n"));
96 
97 	if (connected) {
98 		*__os << LPS_PRINT_JOB << printer << '\n' << flush;
99 		checkAck();
100 	}
101 }
102 
103 void LpsClient::receiveControlFile(int size, const char *name) throw(LPSException)
104 {
105 //	DBGMSG(("tell_receive_control_file\n"));
106 
107 	if (connected) {
108 
109 		char cfname[32];
110 		strncpy(cfname, name, sizeof(cfname));
111 		cfname[sizeof(cfname) - 1] = '\0';
112 
113 		*__os << LPS_RECEIVE_CONTROL_FILE << size << ' ' << cfname << '\n' << flush;
114 
115 		checkAck();
116 	}
117 }
118 
119 void LpsClient::receiveDataFile(int size, const char *name) throw(LPSException)
120 {
121 //	DBGMSG(("tell_receive_data_file\n"));
122 
123 	if (connected) {
124 
125 		char dfname[32];
126 		strncpy(dfname, name, sizeof(dfname));
127 		dfname[sizeof(dfname) - 1] = '\0';
128 
129 		*__os << LPS_RECEIVE_DATA_FILE << size << ' ' << dfname << '\n' << flush;
130 
131 		checkAck();
132 	}
133 }
134 
135 void LpsClient::transferData(const char *buffer, int size) throw(LPSException)
136 {
137 //	DBGMSG(("send: %d\n", size));
138 
139 	if (connected) {
140 
141 		if (size < 0) {
142 			size = strlen(buffer);
143 		}
144 
145 		if (!__os->write(buffer, size)) {
146 			close();
147 			throw(LPSException("error talking to lpd server"));
148 		}
149 	}
150 }
151 
152 void LpsClient::transferData(istream &is, int size) throw(LPSException)
153 {
154 //	DBGMSG(("send: %d\n", size));
155 
156 	if (connected) {
157 
158 		if (size < 0) {
159 			is.seekg(0, ios::end);
160 			size = is.tellg();
161 			is.seekg(0, ios::beg);
162 		}
163 
164 		char c;
165 		while (is.get(c)) {
166 			if (!__os->put(c)) {
167 				close();
168 				throw(LPSException("error reading file."));
169 				return;
170 			}
171 		}
172 	}
173 }
174 
175 void LpsClient::endTransfer() throw(LPSException)
176 {
177 //	DBGMSG(("tell_end_transfer\n"));
178 
179 	if (connected) {
180 		*__os << LPS_END_TRANSFER << flush;
181 		checkAck();
182 	}
183 }
184 
185 void LpsClient::checkAck() throw(LPSException)
186 {
187 //	DBGMSG(("check_ack\n"));
188 
189 	if (connected) {
190 
191 		char c;
192 
193 		if (!__is->get(c)) {
194 			close();
195 			throw(LPSException("server not responding."));
196 			return;
197 		}
198 
199 		switch (c) {
200 		case LPS_OK:
201 			break;
202 		case LPS_ERROR:
203 			close();
204 			throw(LPSException("server error."));
205 			break;
206 		case LPS_NO_SPOOL_SPACE:
207 			close();
208 			throw(LPSException("not enough spool space on server."));
209 			break;
210 		}
211 	}
212 }
213