/*!\brief Descriptor des Sockets auslesen * * \desc * Mit dieser Funktion kann der Betriebssystem-spezifische Socket-Descriptor ausgelesen werden. * Unter Unix ist dies ein File-Descriptor vom Typ Integer, unter Windows ein Socket-Descriptor * vom Typ SOCKET. * * @return Betriebsystem-spezifischer Descriptor. * @exception NotConnectedException Wird geworfen, wenn kein Socket geöffnet ist */ int UDPSocket::getDescriptor() { if (socket==NULL) throw NotConnectedException(); PPLSOCKET *s = (PPLSOCKET*) socket; #ifdef _WIN32 if ((int)s->sd<0) throw NotConnectedException(); return (int)s->sd; #else if (s->sd<0) throw NotConnectedException(); return s->sd; #endif }
void Client::startConversation(const std::string& playerName) const { // rest assured the client is connected to a server before trying to access it if(!_isConnected) throw NotConnectedException("not connected."); else if(!_userTerminal.hasKnownTerminal()) throw std::runtime_error("no known terminal."); else if(playerName == _name) throw std::runtime_error("chatting with yourself is not allowed."); else if(!isFriend(playerName)) throw std::runtime_error("you are only allowed to chat with your friends."); std::string cmd { _userTerminal.startProgram( "WizardPoker_chat", { "caller", // parameter 1 is caller/callee _serverAddress.toString(), // parameter 2 is the address to connect to std::to_string(_serverPort), // parameter 3 is the port to connect to _name, // parameter 4 is caller's name playerName, // parameter 5 is callee's name (_isGui ? "gui" : "terminal") // there is not more parameters! }, not _isGui) }; system(cmd.c_str()); }
const FriendsList& Client::getFriendshipRequests() { if(!_isConnected) throw NotConnectedException("unable to send friendship requests."); updateFriendshipRequests(); return _friendshipRequests; }
FriendsList Client::getConnectedFriends() { if(!_isConnected) throw NotConnectedException("unable to send connected friends."); updateFriends(); FriendsList connectedFriends; for(const auto& friendUser: _friends) { // ask the server if player is conencted sf::Packet packet; packet << TransferType::CHECK_PRESENCE << friendUser.name; _socket.send(packet); _socket.receive(packet); TransferType type; packet >> type; if(type == TransferType::FAILURE) throw std::runtime_error("Unable to check " + friendUser.name + " presence: not friends"); bool isPresent; packet >> isPresent; // add to vector only if friend is present if(isPresent) connectedFriends.push_back(friendUser); } return connectedFriends; }
void LocalServerConnection<BufferType>::Close() { m_pendingChannels->Break(NotConnectedException()); while(!m_pendingChannels->IsEmpty()) { PendingChannelEntry* entry = m_pendingChannels->Top(); m_pendingChannels->Pop(); entry->m_result.SetException(ConnectException("Server unavailable.")); } }
void Client::removeFriend(const std::string& name) { if(!_isConnected) throw NotConnectedException("unable to remove friend."); if(!isFriend(name)) throw std::runtime_error(name + "is not a friend of yours."); sf::Packet packet; // send that the user remove name from its friend list packet << TransferType::REMOVE_FRIEND; packet << name; _socket.send(packet); _socket.receive(packet); TransferType responseHeader; packet >> responseHeader; if(responseHeader != TransferType::ACKNOWLEDGE) throw std::runtime_error("failed to remove " + name + " from your friend list."); }
void Client::sendFriendshipRequest(const std::string& name) { if(!_isConnected) throw NotConnectedException("unable to ask a new friend."); // Cannot be friend with yourself if(name == _name) throw std::runtime_error("can't be friend with yourself."); // Don't ask a friend to become your friend if(isFriend(name)) throw std::runtime_error(name + "is already your friend."); sf::Packet packet; packet << TransferType::NEW_FRIEND << name; _socket.send(packet); // server acknowledges with ACKNOWLEDGE if request was correctly made and by NOT_EXISTING_FRIEND otherwise _socket.receive(packet); TransferType responseHeader; packet >> responseHeader; if(responseHeader != TransferType::ACKNOWLEDGE) throw std::runtime_error("failed to send a request to " + name + "."); }
Buffer WbemExecClient::issueRequest(const Buffer& request) { if (!_connected) { throw NotConnectedException(); } HTTPMessage* httpRequest = new HTTPMessage(request); // Note: A historical defect in the calculation of the Content-Length // header makes it possible that wbemexec input files exist with a // Content-Length value one larger than the actual content size. Adding // and extra newline character to the end of the message keeps those old // scripts working. httpRequest->message << "\n"; _authenticator.setRequestMessage(httpRequest); Boolean haveBeenChallenged = false; HTTPMessage* httpResponse; while (1) { HTTPMessage* httpRequestCopy = new HTTPMessage(*(HTTPMessage*)_authenticator.getRequestMessage()); _addAuthHeader(httpRequestCopy); Message* response = _doRequest(httpRequestCopy); PEGASUS_ASSERT(response->getType() == HTTP_MESSAGE); httpResponse = (HTTPMessage*)response; // If we've already been challenged or if the response does not // contain a challenge, there is nothing more to do. String startLine; Array<HTTPHeader> headers; Uint32 contentLength; httpResponse->parse(startLine, headers, contentLength); if (haveBeenChallenged || !_checkNeedToResend(headers)) { break; } // If the challenge contains a Connection: Close header, reestablish // the connection. String connectionHeader; if (HTTPMessage::lookupHeader( headers, "Connection", connectionHeader, false)) { if (String::equalNoCase(connectionHeader, "Close")) { _reconnect(); } } // Prompt for a password, if necessary if ((_password == String::EMPTY) && _isRemote) { _password = _promptForPassword(); _authenticator.setPassword(_password); } haveBeenChallenged = true; delete httpResponse; } AutoPtr<HTTPMessage> origRequest( (HTTPMessage*)_authenticator.releaseRequestMessage()); AutoPtr<HTTPMessage> destroyer(httpResponse); return httpResponse->message; }
Message* CIMClientRep::_doRequest( AutoPtr<CIMRequestMessage>& request, const Uint32 expectedResponseMessageType ) { if (!_connected) { request.reset(); throw NotConnectedException(); } String messageId = XmlWriter::getNextMessageId(); const_cast<String &>(request->messageId) = messageId; _authenticator.setRequestMessage(0); // ATTN-RK-P2-20020416: We should probably clear out the queue first. PEGASUS_ASSERT(getCount() == 0); // Shouldn't be any messages in our queue // // Set HTTP method in request to POST // //Bug 478/418 - Change this to do post call, not mpost request->setHttpMethod (HTTP_METHOD__POST); // l10n // Set the Accept-Languages and Content-Languages into // the request message request->operationContext.set(AcceptLanguageListContainer(requestAcceptLanguages)); request->operationContext.set(ContentLanguageListContainer(requestContentLanguages)); //gathering statistical information about client operation ClientPerfDataStore* perfDataStore = ClientPerfDataStore::Instance(); perfDataStore->reset(); perfDataStore->setOperationType(request->getType()); perfDataStore->setMessageID(request->messageId); // Sending a new request, so clear out the response Content-Languages responseContentLanguages = ContentLanguages::EMPTY; _requestEncoder->enqueue(request.get()); request.release(); Uint64 startMilliseconds = TimeValue::getCurrentTime().toMilliseconds(); Uint64 nowMilliseconds = startMilliseconds; Uint64 stopMilliseconds = nowMilliseconds + _timeoutMilliseconds; while (nowMilliseconds < stopMilliseconds) { // // Wait until the timeout expires or an event occurs: // _monitor->run(Uint32(stopMilliseconds - nowMilliseconds)); // // Check to see if incoming queue has a message // Message* response = dequeue(); if (response) { // Shouldn't be any more messages in our queue PEGASUS_ASSERT(getCount() == 0); // // Reconnect to reset the connection // if Server response contained a Connection: Close Header // if (response->getCloseConnect() == true) { _reconnect(); response->setCloseConnect(false); } // // Future: If M-POST is used and HTTP response is 501 Not // Implemented or 510 Not Extended, retry with POST method // if (response->getType() == CLIENT_EXCEPTION_MESSAGE) { Exception* clientException = ((ClientExceptionMessage*)response)->clientException; delete response; AutoPtr<Exception> d(clientException); // Make the ContentLanguage of the exception available through // the CIMClient API (its also available in the exception). responseContentLanguages = clientException->getContentLanguages(); // // Determine and throw the specific class of client exception // CIMClientMalformedHTTPException* malformedHTTPException = dynamic_cast<CIMClientMalformedHTTPException*>( clientException); if (malformedHTTPException) { throw *malformedHTTPException; } CIMClientHTTPErrorException* httpErrorException = dynamic_cast<CIMClientHTTPErrorException*>( clientException); if (httpErrorException) { throw *httpErrorException; } CIMClientXmlException* xmlException = dynamic_cast<CIMClientXmlException*>(clientException); if (xmlException) { throw *xmlException; } CIMClientResponseException* responseException = dynamic_cast<CIMClientResponseException*>(clientException); if (responseException) { throw *responseException; } CIMException* cimException = dynamic_cast<CIMException*>(clientException); if (cimException) { throw *cimException; } throw *clientException; } else if (response->getType() == expectedResponseMessageType) { CIMResponseMessage* cimResponse = (CIMResponseMessage*)response; if (cimResponse->messageId != messageId) { // l10n // CIMClientResponseException responseException( // String("Mismatched response message ID: Got \"") + // cimResponse->messageId + "\", expected \"" + // messageId + "\"."); MessageLoaderParms mlParms( "Client.CIMClient.MISMATCHED_RESPONSE", "Mismatched response message ID: Got \"$0\", " "expected \"$1\".", cimResponse->messageId, messageId); String mlString(MessageLoader::getMessage(mlParms)); CIMClientResponseException responseException(mlString); delete response; throw responseException; } // l10n // Get the Content-Languages from the response's operationContext // and make available through the CIMClient API responseContentLanguages = ((ContentLanguageListContainer)cimResponse->operationContext.get (ContentLanguageListContainer::NAME)).getLanguages(); if (cimResponse->cimException.getCode() != CIM_ERR_SUCCESS) { CIMException cimException( cimResponse->cimException.getCode(), cimResponse->cimException.getMessage()); cimException.setContentLanguages(responseContentLanguages); delete response; throw cimException; } /* if excicution gets here everytihng is working correctly and a proper response was generated and recived */ //check that client side statistics are valid before handing them to the // client application via a call back Boolean re_check = perfDataStore->checkMessageIDandType(cimResponse->messageId, cimResponse->getType()); if (re_check && !perfDataStore->getStatError() && perfDataStore->isClassRegistered()) { //if callback method throws an exception it will be seen by the client //no try/catch block is used here intentionaly - becasue exceptions //come from the client application so client app. should handle them ClientOpPerformanceData item = perfDataStore->createPerfDataStruct(); perfDataStore->handler_prt->handleClientOpPerformanceData(item); }//end of if statmet that call the callback method return response; } else if (dynamic_cast<CIMRequestMessage*>(response) != 0) { // Respond to an authentication challenge _requestEncoder->enqueue(response); nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds(); stopMilliseconds = nowMilliseconds + _timeoutMilliseconds; continue; } else { // l10n // CIMClientResponseException responseException( // "Mismatched response message type."); MessageLoaderParms mlParms( "Client.CIMOperationResponseDecoder.MISMATCHED_RESPONSE_TYPE", "Mismatched response message type."); String mlString(MessageLoader::getMessage(mlParms)); CIMClientResponseException responseException(mlString); delete response; throw responseException; } } nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds(); pegasus_yield(); } // // Reconnect to reset the connection (disregard late response) // try { _reconnect(); } catch (...) { } // // Throw timed out exception: // throw ConnectionTimeoutException(); }
/*!\brief Lese-Timeout festlegen * * Mit dieser Funktion kann ein Timeout für Lesezugriffe gesetzt werden. Normalerweise * blockiert eine Leseoperation mit "Read" solange, bis die angeforderten Daten * eingegangen sind (ausser der Socket wurde mit TCPSocket::setBlocking auf "Non-Blocking" * gesetzt). Mit dieser Funktion kann jedoch ein beliebiger mikrosekunden genauer * Timeout festgelegt werden. Der Timeout errechnet sich dabei aus * \p seconds + \p useconds. * \par * Um den Timeout wieder abzustellen, kann die Funktion mit 0 als * Wert für \p seconds und \p useconds aufgerufen werden. * * @param[in] seconds Anzahl Sekunden * @param[in] useconds Anzahl Mikrosekunden (1000000 Mikrosekunden = 1 Sekunde) * @exception NotConnectedException * @exception InvalidSocketException * @exception BadFiledescriptorException * @exception UnknownOptionException * @exception BadAddressException * @exception InvalidArgumentsException */ void UDPSocket::setTimeoutRead(int seconds, int useconds) { if (!connected) throw NotConnectedException(); struct timeval tv; tv.tv_sec = seconds; tv.tv_usec = useconds; PPLSOCKET *s = (PPLSOCKET*) socket; #ifdef WIN32 if (setsockopt(s->sd,SOL_SOCKET,SO_RCVTIMEO,(const char*)&tv,sizeof(tv))!=0) { #else if (setsockopt(s->sd, SOL_SOCKET, SO_RCVTIMEO, (void*) &tv, sizeof(tv)) != 0) { #endif throwExceptionFromErrno(errno, "setTimeoutRead"); } } /*!\brief Schreib-Timeout festlegen * * Mit dieser Funktion kann ein Timeout für Schreibzugriffe gesetzt werden. Normalerweise * blockiert eine Schreiboperation mit "Write" solange, bis alle Daten gesendet wurden. * Mit dieser Funktion kann jedoch ein beliebiger mikrosekunden genauer * Timeout festgelegt werden. Der Timeout errechnet sich dabei aus * \p seconds + \p useconds. * \par * Um den Timeout wieder abzustellen, kann die Funktion mit 0 als * Wert für \p seconds und \p useconds aufgerufen werden. * * @param[in] seconds Anzahl Sekunden * @param[in] useconds Anzahl Mikrosekunden (1000000 Mikrosekunden = 1 Sekunde) * @exception NotConnectedException * @exception InvalidSocketException * @exception BadFiledescriptorException * @exception UnknownOptionException * @exception BadAddressException * @exception InvalidArgumentsException */ void UDPSocket::setTimeoutWrite(int seconds, int useconds) { if (!connected) throw NotConnectedException(); struct timeval tv; tv.tv_sec = seconds; tv.tv_usec = useconds; PPLSOCKET *s = (PPLSOCKET*) socket; #ifdef WIN32 if (setsockopt(s->sd,SOL_SOCKET,SO_SNDTIMEO,(const char*)&tv,sizeof(tv))!=0) { #else if (setsockopt(s->sd, SOL_SOCKET, SO_SNDTIMEO, (void*) &tv, sizeof(tv)) != 0) { #endif throwExceptionFromErrno(errno, "setTimeoutRead"); } } /*!\brief Auf eingehende Daten warten * * \desc * Diese Funktion prüft, ob Daten eingegangen sind. Ist dies der Fall, * kehrt sie sofort wieder zurück. Andernfalls wartet sie solange, bis * Daten eingehen, maximal aber die mit \p seconds und \p useconds * angegebene Zeitspanne. Falls \p seconds und \p useconds Null sind, und * keine Daten bereitstehen, kehrt die Funktion sofort zurück. * * @param[in] seconds Anzahl Sekunden, die gewartet werden soll * @param[in] useconds Anzahl Mikrosekunden, die gewartet werden soll * @return Die Funktion gibt \b true zurück, wenn Daten zum Lesen bereitstehen, * sonst \b false. Im Fehlerfall wird eine Exception geworfen. * @exception Diverse */ bool UDPSocket::waitForIncomingData(int seconds, int useconds) { if (!connected) throw NotConnectedException(); PPLSOCKET *s=(PPLSOCKET*)socket; fd_set rset, wset, eset; struct timeval timeout; timeout.tv_sec=seconds; timeout.tv_usec=useconds; FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset); FD_SET(s->sd,&rset); // Wir wollen nur prüfen, ob was zu lesen da ist int ret=select(s->sd+1,&rset,&wset,&eset,&timeout); if (ret<0) { throwExceptionFromErrno(errno, "UDPSocket::waitForIncomingData"); } if (FD_ISSET(s->sd,&eset)) { throw OutOfBandDataReceivedException("UDPSocket::waitForIncomingData"); } // Falls Daten zum Lesen bereitstehen, könnte dies auch eine Verbindungstrennung anzeigen if (FD_ISSET(s->sd,&rset)) { char buf[2]; ret=recv(s->sd, buf,1, MSG_PEEK|MSG_DONTWAIT); // Kommt hier ein Fehler zurück? if (ret<0) { throwExceptionFromErrno(errno, "UDPSocket::isReadable"); } // Ein Wert von 0 zeigt an, dass die Verbindung getrennt wurde if (ret==0) { throw BrokenPipeException(); } return true; } return false; } /*!\brief Warten, bis der Socket beschreibbar ist * * \desc * Diese Funktion prüft, ob Daten auf den Socket geschrieben werden können. * Ist dies der Fall, kehrt sie sofort wieder zurück. Andernfalls wartet * sie solange, bis der Socket beschrieben werden kann, maximal aber die * mit \p seconds und \p useconds angegebene Zeitspanne. * Falls \p seconds und \p useconds Null sind, und * keine Daten gesendet werden können, kehrt die Funktion sofort zurück. * * @param[in] seconds Anzahl Sekunden, die gewartet werden soll * @param[in] useconds Anzahl Mikrosekunden, die gewartet werden soll * @return Die Funktion gibt \b true zurück, wenn Daten geschrieben werden können, * sonst \b false. Im Fehlerfall wird eine Exception geworfen. * @exception Diverse * */ bool UDPSocket::waitForOutgoingData(int seconds, int useconds) { if (!connected) throw NotConnectedException(); PPLSOCKET *s=(PPLSOCKET*)socket; fd_set rset, wset, eset; struct timeval timeout; timeout.tv_sec=seconds; timeout.tv_usec=useconds; FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset); FD_SET(s->sd,&wset); // Wir wollen nur prüfen, ob wir schreiben können int ret=select(s->sd+1,&rset,&wset,&eset,&timeout); if (ret<0) { throwExceptionFromErrno(errno, "UDPSocket::waitForOutgoingData"); } if (FD_ISSET(s->sd,&eset)) { throw OutOfBandDataReceivedException("UDPSocket::waitForIncomingData"); } if (FD_ISSET(s->sd,&wset)) { return true; } return false; } /*!\brief Bei Lesezugriffen blockieren * * \desc * Durch Aufruf dieser Funktion kann festgelegt werden, ob der Socket bei Lesezugriffen * blockieren soll. Nach dem Öffnen des Sockets ist dieser defaultmäßig so * eingestellt, dass er bei Lesezugriffen solange blockiert (wartet), bis Daten zur * Verfügung stehen. Wird er auf "Non-Blocking" gestellt, kehren die Lese-Funktionen * sofort mit einer Fehlermeldung zurück, wenn noch keine Daten bereitstehen. * * @param[in] value Der Wert "true" setzt den Socket in den Blocking-Modus, was auch der * Default ist. Durch den Wert "false" wird er in den Non-Blocking-Modus gesetzt. * @exception Diverse */ void UDPSocket::setBlocking(bool value) { PPLSOCKET *s=(PPLSOCKET*)socket; if((!s) || (!s->sd)) throw NotConnectedException(); int ret=0; #ifdef _WIN32 u_long v; if (value) { v=0; ret=ioctlsocket(s->sd,FIONBIO,NULL); } else { v=1; ret=ioctlsocket(s->sd,FIONBIO,&v); } if (ret==0) return; throwExceptionFromErrno(errno, "UDPSocket::setBlocking"); #else if (value) ret=fcntl(s->sd,F_SETFL,fcntl(s->sd,F_GETFL,0)&(~O_NONBLOCK)); // Blocking else ret=fcntl(s->sd,F_SETFL,fcntl(s->sd,F_GETFL,0)|O_NONBLOCK);// NON-Blocking if (ret<0) throwExceptionFromErrno(errno, "UDPSocket::setBlocking"); #endif } /*!\brief Socket auf eine IP-Adresse und Port binden * * \desc * Diese Funktion muss aufgerufen werden, bevor man mit CTCPSocket::Listen einen TCP-Server starten kann. Dabei wird mit \p host * die IP-Adresse festgelegt, auf die sich der Server binden soll und mit \p port der TCP-Port. * Es ist nicht möglich einen Socket auf mehrere Adressen zu binden. * * @param[in] host IP-Adresse, Hostname oder "*". Bei Angabe von "*" bindet sich der Socket auf alle * Interfaces des Servers. * @param[in] port Der gewünschte TCP-Port * @exception OutOfMemoryException * @exception ResolverException * @exception SettingSocketOptionException * @exception CouldNotBindToInterfaceException * @exception CouldNotOpenSocketException */ void UDPSocket::bind(const String &host, int port) { //int addrlen=0; if (!socket) { socket=malloc(sizeof(PPLSOCKET)); if (!socket) throw OutOfMemoryException(); PPLSOCKET *s=(PPLSOCKET*)socket; s->sd=0; s->proto=6; s->ipname=NULL; s->port=port; //s->addrlen=0; } #ifdef _WIN32 SOCKET listenfd=0; #else int listenfd=0; #endif PPLSOCKET *s=(PPLSOCKET*)socket; if (s->sd) disconnect(); if (s->ipname) free(s->ipname); s->ipname=NULL; struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags=AI_PASSIVE; hints.ai_family=AF_UNSPEC; hints.ai_socktype=SOCK_DGRAM; int on=1; // Prüfen, ob host ein Wildcard ist struct addrinfo *res; if (host.notEmpty()==true && host!="*") { char portstr[10]; sprintf(portstr,"%i",port); int n; if ((n=getaddrinfo(host,portstr,&hints,&res))!=0) { throw ResolverException("%s, %s",(const char*)host,gai_strerror(n)); } struct addrinfo *ressave=res; do { listenfd=::socket(res->ai_family,res->ai_socktype,res->ai_protocol); if (listenfd<0) continue; // Error, try next one #ifdef _WIN32 if (setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on))!=0) { #else if (setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))!=0) { #endif freeaddrinfo(ressave); throw SettingSocketOptionException(); } if (::bind(listenfd,res->ai_addr,res->ai_addrlen)==0) { //addrlen=res->ai_addrlen; break; } ::shutdown(listenfd,2); #ifdef _WIN32 closesocket(listenfd); #else close(listenfd); #endif listenfd=0; } while ((res=res->ai_next)!=NULL); freeaddrinfo(ressave); } else { // Auf alle Interfaces binden listenfd=::socket(AF_INET, SOCK_STREAM, 0); if (listenfd>=0) { struct sockaddr_in addr; memset(&addr,0,sizeof(addr)); addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(port); addr.sin_family = AF_INET; /* bind server port */ if(::bind(listenfd, (struct sockaddr *) &addr, sizeof(addr))!=0) { ::shutdown(listenfd,2); #ifdef _WIN32 closesocket(listenfd); #else close(listenfd); #endif throw CouldNotBindToInterfaceException("Host: *, Port: %d",port); } s->sd=listenfd; connected=1; return; } } if (listenfd<0) { throw CouldNotOpenSocketException("Host: %s, Port: %d",(const char*)host,port); } if (res==NULL) { throw CouldNotBindToInterfaceException("Host: %s, Port: %d",(const char*)host,port); } s->sd=listenfd; connected=1; } /*!\brief Daten schreiben * * \desc * Mit dieser Funktionen werden \p bytes Bytes aus dem Speicherbereich \p buffer an die Gegenstelle * gesendet. * * @param[in] buffer Pointer auf die zu sendenden Daten * @param[in] bytes Anzahl zu sendender Bytes * @return Wenn die Daten erfolgreich geschrieben wurden, gibt die Funktion die Anzahl geschriebener * Bytes zurück. Im Fehlerfall wird eine Exception geworfen. */ size_t UDPSocket::write(const void *buffer, size_t bytes) { if (!connected) throw NotConnectedException(); PPLSOCKET *s = (PPLSOCKET*) socket; if (!buffer) throw InvalidArgumentsException(); size_t BytesWritten = 0; if (bytes) { size_t rest = bytes; ssize_t b = 0; while (rest) { b = ::send(s->sd, (char *) buffer, rest, 0); if (b > 0) { BytesWritten += b; rest -= b; buffer = ((const char*) buffer) + b; } #ifdef WIN32 if (b==SOCKET_ERROR) { #else if (b < 0) { #endif if (errno == EAGAIN) { waitForOutgoingData(0, 100000); } else { throwExceptionFromErrno(errno, "UDPSocket::write"); } } } } return BytesWritten; } size_t UDPSocket::write(const String &str, size_t bytes) { if (bytes>0 && bytes<=str.size()) { return write(str.getPtr(),bytes); } return write(str.getPtr(),str.size()); } size_t UDPSocket::write(const WideString &str, size_t bytes) { if (bytes>0 && bytes<=str.byteLength()) { return write(str.getPtr(),bytes); } return write(str.getPtr(),str.byteLength()); } size_t UDPSocket::write(const ByteArrayPtr &bin, size_t bytes) { if (bytes>0 && bytes<=bin.size()) { return write(bin.ptr(),bytes); } return write(bin.ptr(),bin.size()); } size_t UDPSocket::writef(const char *fmt, ...) { if (!fmt) throw IllegalArgumentException(); String str; va_list args; va_start(args, fmt); str.vasprintf(fmt,args); va_end(args); return write(str); } #ifdef TODO void UDPSocket::setTimeoutRead(int seconds, int useconds) /*! \brief Timeout setzen * * \header \#include <ppl6.h> * \desc * Mit dieser Funktion wird der Timeout für das Empfangen von Daten gesetzt. * * \param seconds Anzahl Sekunden * \param useconds Anzahl Millisekunden * \note Diese Funktion hat zur Zeit noch keine Auswirkungen * \since Wurde mit Version 6.0.19 eingeführt */ { timeout_sec=seconds; timeout_usec=useconds; } #endif #ifdef TODO size_t UDPSocket::sendTo(const String &host, int port, const String &buffer) /*! \brief UDP-Packet verschicken * * \header \#include <ppl6.h> * \desc * Mit dieser Funktion wird ein UDP-Paket an den angegebenen Host verschickt. * * \param host Der Name oder die IP-Adresse des Zielrechners * \param port Der Port des Zielrechners * \param buffer Ein Pointer auf eine String-Klasse, die die zu sendenden Daten enthält * \returns Im Erfolgsfall liefert die Funktion die Anzahl gesendeter Bytes zurück, im Fehlerfall -1. * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden * * \since Wurde mit Version 6.0.19 eingeführt */ { return sendTo(host,port,(const void *)buffer.getPtr(),buffer.len()); } size_t UDPSocket::sendTo(const String &host, int port, const void *buffer, size_t bytes) /*! \brief UDP-Packet verschicken * * \header \#include <ppl6.h> * \desc * Mit dieser Funktion wird ein UDP-Paket an den angegebenen Host verschickt. * * \param host Der Name oder die IP-Adresse des Zielrechners * \param port Der Port des Zielrechners * \param buffer Ein Pointer auf den Puffer, der die zu sendenden Daten enthält * \param bytes Die Anzahl Bytes im Puffer, die gesendet werden sollen * \returns Im Erfolgsfall liefert die Funktion die Anzahl gesendeter Bytes zurück, im Fehlerfall -1. * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden * * \since Wurde mit Version 6.0.19 eingeführt */ { if (!host) { ppl6::SetError(194,"int UDPSocket::SendTo(==> char *host <== , int port, void *buffer, int bytes)"); return -1; } if (!port) { ppl6::SetError(194,"int UDPSocket::SendTo(char *host, ==> int port <== , void *buffer, int bytes)"); return -1; } if (!buffer) { ppl6::SetError(194,"int UDPSocket::SendTo(char *host, int port, ==> void *buffer <== , int bytes)"); return -1; } if (bytes<0) { ppl6::SetError(194,"int UDPSocket::SendTo(char *host, int port, void *buffer, ==> int bytes <== )"); return -1; } ppl6::CAssocArray res, *a; ppl6::CBinary *bin; if (!ppl6::GetHostByName(host,&res)) return -1; a=res.GetFirstArray(); //a->List(); int domain, type, protocol; domain=ppl6::atoi(a->Get("ai_family")); type=ppl6::atoi(a->Get("ai_socktype")); //protocol=ppl6::atoi(a->Get("ai_protocol")); struct protoent *proto=getprotobyname("UDP"); if (!proto) { ppl6::SetError(395); return -1; } protocol=proto->p_proto; bin=a->GetBinary("ai_addr"); //a->List(); const struct sockaddr *to=(const struct sockaddr *)bin->GetPtr(); ((sockaddr_in*)to)->sin_port=htons(port); PPLSOCKET *s=(PPLSOCKET*)socket; if (!s) { socket=malloc(sizeof(PPLSOCKET)); s=(PPLSOCKET*)socket; s->sd=-1; } else if ((int)s->sd>-1) { ppl_closesocket(s->sd); } s->sd=::socket(domain,SOCK_DGRAM,protocol); //sockfd=::socket(AF_INET,SOCK_DGRAM,0); if (s->sd<0) { SetSocketError(); return -1; } #ifdef _WIN32 int ret=::sendto(s->sd,(const char*)buffer,bytes,0,to,bin->GetSize()); #else ssize_t ret=::sendto(s->sd,(const void*)buffer,(size_t)bytes,0,to,(socklen_t) bin->GetSize()); #endif if (ret<0) { printf ("ret: %i\n",(int)ret); SetSocketError(); return -1; } //close(sockfd); return ret; } int UDPSocket::RecvFrom(CString &buffer, int maxlen) /*! \brief UDP-Packet empfangen * * \header \#include <ppl6.h> * \desc * Diese Funktion wartet auf ein UDP-Packet * * \param buffer Ein Pointer auf eine String-Klasse, in die die Daten geschrieben werden sollen * \param maxlen Die maximale Anzahl Bytes, die in den Puffer geschrieben werden können * \returns Im Erfolgsfall liefert die Funktion die Anzahl gelesener Bytes zurück, im Fehlerfall -1. * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden * * \since Wurde mit Version 6.0.19 eingeführt */ { char *b=(char*)malloc(maxlen+1); if (!b) { SetError(2); return 0; } int ret=RecvFrom((void*)b,maxlen); buffer.ImportBuffer(b,maxlen); return ret; }
Message* CIMExportClient::_doRequest( CIMRequestMessage* pRequest, MessageType expectedResponseMessageType) { PEG_METHOD_ENTER (TRC_EXPORT_CLIENT, "CIMExportClient::_doRequest()"); AutoPtr<CIMRequestMessage> request(pRequest); if (!_connected && !_doReconnect) { PEG_METHOD_EXIT(); throw NotConnectedException(); } if (_doReconnect) { try { _connect(); _doReconnect = false; } catch (const Exception& e) { PEG_TRACE((TRC_EXPORT_CLIENT, Tracer::LEVEL1, "Failed to connect to indication listener: %s", (const char*)e.getMessage().getCString())); PEG_METHOD_EXIT(); throw; } catch (...) { PEG_TRACE_CSTRING(TRC_EXPORT_CLIENT, Tracer::LEVEL1, "Failed to connect to indication listener."); PEG_METHOD_EXIT(); throw; } } String messageId = XmlWriter::getNextMessageId(); const_cast<String &>(request->messageId) = messageId; _authenticator.setRequestMessage(0); // ATTN-RK-P2-20020416: We should probably clear out the queue first. PEGASUS_ASSERT(getCount() == 0); // Shouldn't be any messages in our queue // // Set HTTP method in request to POST // request->setHttpMethod(HTTP_METHOD__POST); _requestEncoder->enqueue(request.release()); Uint64 startMilliseconds = TimeValue::getCurrentTime().toMilliseconds(); Uint64 nowMilliseconds = startMilliseconds; Uint64 stopMilliseconds = nowMilliseconds + _timeoutMilliseconds; while (nowMilliseconds < stopMilliseconds) { // // Wait until the timeout expires or an event occurs: // _monitor->run(Uint32(stopMilliseconds - nowMilliseconds)); // // Check to see if incoming queue has a message // AutoPtr<Message> response(dequeue()); if (response.get() != 0) { // Shouldn't be any more messages in our queue PEGASUS_ASSERT(getCount() == 0); // // Close the connection if response contained a "Connection: Close" // header (e.g. at authentication challenge) // if (response->getCloseConnect() == true) { _disconnect(); _doReconnect = true; response->setCloseConnect(false); } // // Future: If M-POST is used and HTTP response is 501 Not // Implemented or 510 Not Extended, retry with POST method // if (response->getType() == CLIENT_EXCEPTION_MESSAGE) { Exception* clientException = ((ClientExceptionMessage*)response.get())->clientException; PEG_TRACE_CSTRING(TRC_EXPORT_CLIENT, Tracer::LEVEL2, "Client Exception Message received."); AutoPtr<Exception> d(clientException); // // Determine and throw the specific class of client exception // CIMClientMalformedHTTPException* malformedHTTPException = dynamic_cast<CIMClientMalformedHTTPException*>( clientException); if (malformedHTTPException) { PEG_METHOD_EXIT(); throw *malformedHTTPException; } CIMClientHTTPErrorException* httpErrorException = dynamic_cast<CIMClientHTTPErrorException*>( clientException); if (httpErrorException) { PEG_METHOD_EXIT(); throw *httpErrorException; } CIMClientXmlException* xmlException = dynamic_cast<CIMClientXmlException*>(clientException); if (xmlException) { PEG_METHOD_EXIT(); throw *xmlException; } CIMClientResponseException* responseException = dynamic_cast<CIMClientResponseException*>(clientException); if (responseException) { PEG_METHOD_EXIT(); throw *responseException; } PEG_METHOD_EXIT(); throw *clientException; } else if (response->getType() == expectedResponseMessageType) { PEG_TRACE_CSTRING(TRC_EXPORT_CLIENT, Tracer::LEVEL4, "Received expected indication response message."); CIMResponseMessage* cimResponse = (CIMResponseMessage*)response.get(); if (cimResponse->messageId != messageId) { MessageLoaderParms mlParms( "ExportClient.CIMExportClient.MISMATCHED_RESPONSE_ID", "Mismatched response message ID: Got \"$0\", " "expected \"$1\".", cimResponse->messageId, messageId); String mlString(MessageLoader::getMessage(mlParms)); CIMClientResponseException responseException(mlString); PEG_METHOD_EXIT(); throw responseException; } if (cimResponse->cimException.getCode() != CIM_ERR_SUCCESS) { PEG_TRACE_CSTRING(TRC_EXPORT_CLIENT, Tracer::LEVEL1, "Received indication failure message."); CIMException cimException( cimResponse->cimException.getCode(), cimResponse->cimException.getMessage()); PEG_METHOD_EXIT(); throw cimException; } PEG_METHOD_EXIT(); return response.release(); } else if (dynamic_cast<CIMRequestMessage*>(response.get()) != 0) { // // Respond to an authentication challenge. // Reconnect if the connection was closed. // if (_doReconnect) { _connect(); } _requestEncoder->enqueue(response.release()); nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds(); stopMilliseconds = nowMilliseconds + _timeoutMilliseconds; continue; } else { MessageLoaderParms mlParms( "ExportClient.CIMExportClient.MISMATCHED_RESPONSE", "Mismatched response message type."); String mlString(MessageLoader::getMessage(mlParms)); CIMClientResponseException responseException(mlString); PEG_TRACE((TRC_EXPORT_CLIENT, Tracer::LEVEL1, (const char*)mlString.getCString())); PEG_METHOD_EXIT(); throw responseException; } } nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds(); } // // Reconnect to reset the connection (disregard late response) // PEG_TRACE_CSTRING(TRC_EXPORT_CLIENT, Tracer::LEVEL2, "Connection to the listener timed out."); _disconnect(); _authenticator.resetChallengeStatus(); _doReconnect = true; // // Throw timed out exception: // PEG_METHOD_EXIT(); throw ConnectionTimeoutException(); }