int PipeIn::write(t_processState &state) { _writeFd = (open(_path.c_str(), O_WRONLY)); if (_writeFd == -1) throw CommunicationError("Error: opening of a named pipe to write in it failed."); if (::write(_writeFd, &state, sizeof(t_processState)) == -1) { destroy(); std::cerr << "Error: Could not write in Pipe" << std::endl; return (-1); } destroy(); return (0); }
// Ensures that input buffer (local data cache) contains at least 'size' elements. // In other words, it refills the 'inBuffer' (local data cache) if it doesn't contain at // least 'size' bytes of data. // // Throws an exception, as indication of failure, in two cases: // 1) we failed to acquire bytes from service // 2) we failed to acquire EXACTLY enough bytes to fill WHOLE input buffer // void QRBG::EnsureCachedEnough(size_t size) throw(ConnectError, CommunicationError, ServiceDenied) { // timer reset timeEnd = timeStart; if (IsCachedEnough(size)) return; try { if (AcquireBytesFromService(inBuffer, inBufferSize) != inBufferSize) throw CommunicationError(); inBufferNextElemIdx = 0; } catch (...) { inBufferNextElemIdx = inBufferSize; // since inBuffer may now be corrupted throw; } }
void SSRC::newSession(const int maxPollResSize) { NewSessionRequest *nsreq = Requests::createNewSessionReq(maxPollResSize); Result *res = NULL; NewSessionResult *nsres = NULL; int maxPollResSizeRecv = NO_MAX_POLL_RES_SIZE; try { res = _xmlCommunication->genericRequest(nsreq); nsres = dynamic_cast<NewSessionResult *>(res); if (!nsres) throw RequestHandlerError("No NewSessionResult" " in response to NewSessionRequest"); maxPollResSizeRecv = nsres->getMaxPollResultSize(); if (maxPollResSize != NO_MAX_POLL_RES_SIZE) if (maxPollResSizeRecv == NO_MAX_POLL_RES_SIZE) throw CommunicationError("Server did not" " set max-poll-result-size" " in newSessionResult"); } catch (...) { // free the memory if (nsreq) delete nsreq; if (nsres) delete nsres; // throw exception up throw; } _currentSessionId = nsres->getSessionId(); _currentPublisherId = nsres->getPublisherId(); _currentMaxPollResSize = maxPollResSizeRecv; delete nsreq; delete nsres; }
// Fills the 'buffer' with maximum of 'count' bytes, explicitly from the remote QRBG Service. // Actual number of bytes copied into the buffer is returned. // Upon failure, exceptions are thrown. // Returns: count of bytes (received) copied into the supplied buffer. size_t QRBG::AcquireBytesFromService(byte* buffer, size_t count) throw(ConnectError, CommunicationError, ServiceDenied) { // connect to the service server, // propagate exception to the caller Connect(); // // prepare and send the request // // NOTE: we're using plain authentication. /* Client first (and last) packet: Size [B] Content -------------- -------------------------------------------------------- 1 operation, from OperationCodes enum if operation == GET_DATA_AUTH_PLAIN, then: 2 content size (= 1 + username_len + 1 + password_len + 4) 1 username_len (must be > 0 and <= 100) username_len username (NOT zero padded!) 1 password_len (must be > 0 and <= 100) password_len password in plain 8-bit ascii text (NOT zero padded!) 4 bytes of data requested Server first (and last) packet: Size [B] Content -------------- -------------------------------------------------------- 1 response, from ServerResponseCodes enum 1 response details - reason, from RefusalReasonCodes 4 data_len, bytes of data that follow data_len data */ // header structure looks like this: // struct tClientHeader { // uint8 eOperation; // MUST BE eOperation == GET_DATA_AUTH_PLAIN for struct remainder to hold // uint16 cbContentSize; // uint8 cbUsername; // char szUsername[cbUsername]; // uint8 cbPassword; // char szPassword[cbPassword]; // uint32 cbRequested; // }; // however, two issues obstruct direct structure usage: // 1) we don't know username/password length apriori // 2) we must convert all numeric values to network order (big endian) // so, we'll fill output buffer byte-by-byte... uint8 eOperation = GET_DATA_AUTH_PLAIN; uint8 cbUsername = static_cast<uint8>( strlen(szUsername) ); uint8 cbPassword = static_cast<uint8>( strlen(szPassword) ); uint32 cbRequested = static_cast<uint32>( count ); uint16 cbContentSize = sizeof(cbUsername) + cbUsername + sizeof(cbPassword) + cbPassword + sizeof(cbRequested); uint32 bytesToSend = sizeof(eOperation) + sizeof(cbContentSize) + cbContentSize; ASSERT(outBufferSize >= bytesToSend); byte* pRequestBuffer = outBuffer; *(uint8*)pRequestBuffer = eOperation, pRequestBuffer += sizeof(eOperation); *(uint16*)pRequestBuffer = htons(cbContentSize), pRequestBuffer += sizeof(cbContentSize); *(uint8*)pRequestBuffer = cbUsername, pRequestBuffer += sizeof(cbUsername); memcpy(pRequestBuffer, szUsername, cbUsername), pRequestBuffer += cbUsername; *(uint8*)pRequestBuffer = cbPassword, pRequestBuffer += sizeof(cbPassword); memcpy(pRequestBuffer, szPassword, cbPassword), pRequestBuffer += cbPassword; *(uint32*)pRequestBuffer = htonl(cbRequested), pRequestBuffer += sizeof(cbRequested); int ret = send(hSocket, (const char*)outBuffer, bytesToSend, 0); if (ret == -1) { // failed to send data request to the server Close(); throw CommunicationError(); } if (ret != bytesToSend) { // failed to send complete data request to the server Close(); throw CommunicationError(); } // // receive header (assuming GET_DATA_AUTH_PLAIN, as we requested) // // server response header structure looks like this: // struct tServerHeader { // uint8 response; // actually from enum ServerResponseCodes // uint8 reason; // actually from enum RefusalReasonCodes // uint32 cbDataLen; // should be equal to cbRequested, but we should not count on it! // }; // however, to avoid packing and memory aligning portability issues, // we'll read input buffer byte-by-byte... ServerResponseCodes eResponse; RefusalReasonCodes eReason; uint32 cbDataLen = 0; const uint32 bytesHeader = sizeof(uint8) + sizeof(uint8) + sizeof(uint32); byte header[bytesHeader]; uint32 bytesReceived = 0; uint32 bytesToReceiveTotal = bytesHeader; uint32 bytesToReceiveNow = 0; // receive header while ( (bytesToReceiveNow = bytesToReceiveTotal - bytesReceived) > 0 ) { int ret = recv(hSocket, (char*)(header + bytesReceived), bytesToReceiveNow, 0); if (ret != -1) { if (ret > 0) { // data received bytesReceived += ret; // parse the server response if (bytesReceived >= 2*sizeof(uint8)) { eResponse = (ServerResponseCodes) header[0]; eReason = (RefusalReasonCodes) header[1]; // process server response... if (eResponse != OK) { Close(); throw ServiceDenied(eResponse, eReason); } if (bytesReceived >= bytesToReceiveTotal) { cbDataLen = ntohl( *((u_long*)(header + 2*sizeof(uint8))) ); } } } else { // recv() returns 0 if connection was closed by server Close(); throw CommunicationError(); } } else { int nErr = GetLastSocketError(); if (nErr == EAGAIN) { // wait a little bit, and try again } else { // some socket(network) error occurred; // it doesn't matter what it is, declare failure! Close(); throw CommunicationError(); } } } // // receive data // bytesReceived = 0; bytesToReceiveTotal = cbDataLen; while ( (bytesToReceiveNow = bytesToReceiveTotal - bytesReceived) > 0 ) { // limit to maximal socket buffer size used bytesToReceiveNow = bytesToReceiveNow < INTERNAL_SOCKET_MAX_BUFFER ? bytesToReceiveNow : INTERNAL_SOCKET_MAX_BUFFER; int ret = recv(hSocket, (char*)(buffer + bytesReceived), bytesToReceiveNow, 0); if (ret != -1) { if (ret > 0) { // data received bytesReceived += ret; } else { // recv() returns 0 if connection was closed by server Close(); throw CommunicationError(); } } else { int nErr = GetLastSocketError(); if (nErr == EAGAIN) { // wait a little bit, and try again } else { // some socket(network) error occurred; // it doesn't matter what it is, declare failure! Close(); throw CommunicationError(); } } } Close(); // we succeeded. return bytesReceived; }