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
16using 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
44LpsClient::LpsClient(const char *host)
45	:
46	fConnected(false),
47	fHost(host),
48	fSock(NULL)
49{
50}
51
52
53LpsClient::~LpsClient()
54{
55	close();
56}
57
58
59void
60LpsClient::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
81void
82LpsClient::close()
83{
84	fConnected = false;
85	if (fSock) {
86		delete fSock;
87		fSock = NULL;
88	}
89}
90
91
92void
93LpsClient::receiveJob(const char *printer)
94{
95	if (fConnected) {
96		*fOutput << LPS_PRINT_JOB << printer << '\n' << flush;
97		checkAck();
98	}
99}
100
101
102void
103LpsClient::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
117void
118LpsClient::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
133void
134LpsClient::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
150void
151LpsClient::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
173void
174LpsClient::endTransfer()
175{
176	if (fConnected) {
177		*fOutput << LPS_END_TRANSFER << flush;
178		checkAck();
179	}
180}
181
182
183void
184LpsClient::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