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