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