Subversion Repositories Programming Utils

Rev

Rev 113 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <log4cxx/logstring.h>
#include <log4cxx/helpers/datagramsocket.h>
#include <log4cxx/helpers/datagrampacket.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/transcoder.h>

#ifndef LOG4CXX_QT
#include "apr_network_io.h"
#include "apr_lib.h"
#else
#include <QHostAddress>
#include <QByteArray>
#endif

using namespace log4cxx::helpers;

IMPLEMENT_LOG4CXX_OBJECT(DatagramSocket)

DatagramSocket::DatagramSocket()
 : socket(0), address(), localAddress(), port(0), localPort(0)
{
   create();
}

DatagramSocket::DatagramSocket(int localPort1)
 : socket(0), address(), localAddress(), port(0), localPort(0)
{
   InetAddressPtr bindAddr = InetAddress::anyAddress();

   create();
   bind(localPort1, bindAddr);
}

DatagramSocket::DatagramSocket(int localPort1, InetAddressPtr localAddress1)
 : socket(0), address(), localAddress(), port(0), localPort(0)
{
   create();
   bind(localPort1, localAddress1);
}

DatagramSocket::~DatagramSocket()
{
   try
   {
      close();
   }
   catch(SocketException&)
   {
   }
}

/**  Binds a datagram socket to a local port and address.*/
void DatagramSocket::bind(int localPort1, InetAddressPtr localAddress1)
{
   Pool addrPool;

   // Create server socket address (including port number)
   LOG4CXX_ENCODE_CHAR(hostAddr, localAddress1->getHostAddress());
#ifndef LOG4CXX_QT
   apr_sockaddr_t *server_addr;
   apr_status_t status =
       apr_sockaddr_info_get(&server_addr, hostAddr.c_str(), APR_INET,
                             localPort1, 0, addrPool.getAPRPool());
   if (status != APR_SUCCESS) {
     throw BindException(status);
   }

   // bind the socket to the address
   status = apr_socket_bind(socket, server_addr);
   if (status != APR_SUCCESS) {
     throw BindException(status);
   }
#else
   QHostAddress localHost( localAddress1->getHostAddress().c_str() );
   bool status = socket->bind( localHost, localPort1 );
   if( !status ){
       throw BindException( status );
   }
#endif

   this->localPort = localPort1;
   this->localAddress = localAddress1;
}

/** Close the socket.*/
void DatagramSocket::close()
{
#ifndef LOG4CXX_QT
   if (socket != 0) {
      apr_status_t status = apr_socket_close(socket);
      if (status != APR_SUCCESS) {
        throw SocketException(status);
      }

      socket = 0;
      localPort = 0;
   }
#else
    if( socket->isOpen() ){
        socket->close();
    }
#endif
}

void DatagramSocket::connect(InetAddressPtr address1, int port1)
{

   this->address = address1;
   this->port = port1;

   Pool addrPool;

   // create socket address
   LOG4CXX_ENCODE_CHAR(hostAddr, address1->getHostAddress());
#ifndef LOG4CXX_QT
   apr_sockaddr_t *client_addr;
   apr_status_t status =
       apr_sockaddr_info_get(&client_addr, hostAddr.c_str(), APR_INET,
                             port, 0, addrPool.getAPRPool());
   if (status != APR_SUCCESS) {
     throw ConnectException(status);
   }

   // connect the socket
   status = apr_socket_connect(socket, client_addr);
   if (status != APR_SUCCESS) {
     throw ConnectException(status);
   }
#else
    socket->connectToHost( address1->getHostAddress().c_str(), port1 );
#endif
}

/** Creates a datagram socket.*/
void DatagramSocket::create()
{
#ifndef LOG4CXX_QT
  apr_socket_t* newSocket;
  apr_status_t status =
    apr_socket_create(&newSocket, APR_INET, SOCK_DGRAM,
                      APR_PROTO_UDP, socketPool.getAPRPool());
  socket = newSocket;
  if (status != APR_SUCCESS) {
    throw SocketException(status);
  }
#else
    socket = new QUdpSocket();
#endif
}

/** Receive the datagram packet.*/
void DatagramSocket::receive(DatagramPacketPtr& p)
{
   Pool addrPool;

   // Create the address from which to receive the datagram packet
   LOG4CXX_ENCODE_CHAR(hostAddr, p->getAddress()->getHostAddress());
#ifndef LOG4CXX_QT
   apr_sockaddr_t *addr;
   apr_status_t status =
       apr_sockaddr_info_get(&addr, hostAddr.c_str(), APR_INET,
                             p->getPort(), 0, addrPool.getAPRPool());
   if (status != APR_SUCCESS) {
     throw SocketException(status);
   }

   // receive the datagram packet
   apr_size_t len = p->getLength();
   status = apr_socket_recvfrom(addr, socket, 0,
                                (char *)p->getData(), &len);
   if (status != APR_SUCCESS) {
     throw IOException(status);
   }
#else
   int length = p->getLength();
   int status = socket->read( (char*)p->getData(), length );
   if( status == -1 ){
       throw IOException( status );
   }
#endif
}

/**  Sends a datagram packet.*/
void DatagramSocket::send(DatagramPacketPtr& p)
{
   Pool addrPool;

   // create the adress to which to send the datagram packet
   LOG4CXX_ENCODE_CHAR(hostAddr, p->getAddress()->getHostAddress());
#ifndef LOG4CXX_QT
   apr_sockaddr_t *addr;
   apr_status_t status =
       apr_sockaddr_info_get(&addr, hostAddr.c_str(), APR_INET, p->getPort(),
                             0, addrPool.getAPRPool());
   if (status != APR_SUCCESS) {
     throw SocketException(status);
   }

   // send the datagram packet
   apr_size_t len = p->getLength();
   status = apr_socket_sendto(socket, addr, 0,
                              (char *)p->getData(), &len);
   if (status != APR_SUCCESS) {
     throw IOException(status);
   }
#else
   int len = p->getLength();
    int status = socket->write( (const char*)p->getData(), len );
    if( status < 0 ){
        throw IOException( status );
    }
#endif
}