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