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