Changeset 5 in libcf++ for trunk/src/network.cpp


Ignore:
Timestamp:
03/21/15 19:54:07 (9 years ago)
Author:
cheese
Message:

#1 get address from local socket or peer socket

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/network.cpp

    r4 r5  
    3737#endif
    3838
    39 #define ALLOW_SOCKET_TIME_WAIT
    40 
    41 cf::socket_t gInvalidSocket = -1;
     39#define INVALID_SOCKET  -1
    4240
    4341/*--------------------------------------------------------------*/
     
    4846long GetMACAddress(cf::char_t *addr);
    4947
     48static std::string convertAddressToString(struct sockaddr_in & addr)
     49{
     50    cf::uint8_t * bytes = NULL;
     51    cf::char_t str[32] = {0x00};
     52
     53    bytes = reinterpret_cast<cf::uint8_t *>(&addr.sin_addr.s_addr);
     54    snprintf(str, sizeof(str) - 1, "%u.%u.%u.%u", bytes[0],
     55                                                  bytes[1],
     56                                                  bytes[2],
     57                                                  bytes[3]);
     58
     59    return str;
     60}
     61
     62static cf::void_t setNonBlocking(const cf::socket_t sock,
     63                                 const cf::bool_t flag)
     64{
     65#ifdef _ON_WINDOWS
     66    cf::ulong_t mode = flag ? 1 : 0;
     67    ioctlsocket(sock, FIONBIO, &mode);
     68#else
     69    cf::int32_t mode = fcntl(sock, F_GETFL, 0);
     70
     71    if (flag)   mode |=  O_NONBLOCK;
     72    else        mode &= ~O_NONBLOCK;
     73
     74    fcntl(sock, F_SETFL, mode);
     75#endif
     76}
     77
    5078static cf::void_t waitForTimeout(const cf::socket_t sock,
    5179                                 const cf::int32_t timeout,
     
    87115}
    88116
    89 static cf::void_t setLinger(cf::network::tcp & tcp)
    90     throw (cf::exception)
    91 {
    92 #ifdef ALLOW_SOCKET_TIME_WAIT
    93     return;
    94 #else
     117static cf::void_t setReuseAddress(const cf::network::tcp & tcp)
     118    throw (cf::exception)
     119{
    95120    try
    96121    {
    97         struct linger linger;
    98 
    99         linger.l_onoff = 1;
    100         linger.l_linger = 0;
    101 
    102         tcp.setOption(SO_LINGER, &linger, sizeof(linger));
     122        cf::int32_t reuseaddr = 1;
     123
     124        tcp.setOption(SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
    103125    }
    104126    catch (cf::exception & e)
     
    106128        FORWARD_EXCEPTION(e);
    107129    }
    108 #endif
    109 }
    110 
    111 static cf::void_t setReuseAddress(cf::network::tcp & tcp)
    112     throw (cf::exception)
    113 {
    114     try
    115     {
    116         cf::int32_t reuseaddr = 1;
    117 
    118         tcp.setOption(SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
    119     }
    120     catch (cf::exception & e)
    121     {
    122         FORWARD_EXCEPTION(e);
    123     }
     130}
     131
     132typedef cf::int32_t (*getSocketNameAPI)(cf::socket_t sock,
     133                                        struct sockaddr * addr,
     134                                        socklen_t *len);
     135
     136static cf::network::host getSocketNameFromFunction(const cf::socket_t sock,
     137                                                   getSocketNameAPI api)
     138    throw (cf::exception)
     139{
     140    cf::int32_t result = 0;
     141    struct sockaddr_in addr;
     142    socklen_t len = sizeof(struct sockaddr_in);
     143
     144    result = api(sock, (struct sockaddr *)&addr, &len);
     145    if (result < 0)
     146        THROW_EXCEPTION("cannot get sockket or peer name ("
     147                        << cf::exception::systemCode()
     148                        << ")");
     149
     150    return cf::network::host(convertAddressToString(addr), addr.sin_port);
    124151}
    125152/*--------------------------------------------------------------*/
     153
     154cf::network::host::host(const std::string & address,
     155                        const cf::uint16_t port)
     156    : mAddress(address),
     157      mPort(port)
     158{
     159}
     160
     161std::string cf::network::host::address() const
     162{
     163    return mAddress;
     164}
     165
     166cf::uint16_t cf::network::host::port() const
     167{
     168    return mPort;
     169}
     170
     171cf::bool_t cf::network::host::empty() const
     172{
     173    return (address().empty() || port() <= 0) ? true : false;
     174}
    126175
    127176cf::network::tcp::tcp(const cf::socket_t attachedSocket)
     
    145194    }
    146195
    147     if (mSocket == gInvalidSocket)
     196    if (mSocket == INVALID_SOCKET)
    148197        mSocket = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    149198
     
    159208cf::void_t cf::network::tcp::close()
    160209{
    161     if (mSocket == gInvalidSocket)
     210    if (mSocket == INVALID_SOCKET)
    162211        return;
    163212
    164213    closesocket(mSocket);
    165214
    166     mSocket = gInvalidSocket;
    167     mHost = "";
    168     mPort = 0;
    169 }
    170 
    171 cf::void_t cf::network::tcp::connect(const cf::char_t * host,
    172                                      const cf::uint16_t port,
     215    mSocket = INVALID_SOCKET;
     216}
     217
     218cf::void_t cf::network::tcp::connect(const cf::network::host & peer,
    173219                                     const cf::int32_t timeout)
    174220    throw (cf::exception)
    175221{
    176     if (!host || !port)
     222    if (peer.empty())
    177223        THROW_EXCEPTION("invalid host info");
    178224
     
    183229    struct hostent * hostEnt;
    184230
     231    const cf::char_t * host = peer.address().c_str();
     232    cf::uint16_t port = peer.port();
     233
    185234    /* 1. set data */
    186235    addr.sin_family         = AF_INET;
     
    204253    try
    205254    {
    206         setLinger(*this);
    207255        setReuseAddress(*this);
    208256    }
     
    212260    }
    213261
    214     if (timeout > 0)
    215         setNonBlocking(true);
     262    setTimeout(timeout);
    216263
    217264    /* 4. connect */
     
    243290        }
    244291    }
    245 
    246     /* set */
    247     mHost = host;
    248     mPort = port;
    249     mTimeout = timeout;
    250292}
    251293
    252294cf::void_t cf::network::tcp::listen(const cf::uint16_t port,
    253                                     const cf::int32_t backlog)
     295                                    const cf::int32_t backlog) const
    254296    throw (cf::exception)
    255297{
     
    268310    try
    269311    {
    270         setLinger(*this);
    271312        setReuseAddress(*this);
    272313    }
     
    285326}
    286327
    287 cf::network::tcp cf::network::tcp::accept()
     328cf::network::tcp cf::network::tcp::accept() const
    288329    throw (cf::exception)
    289330{
     
    302343    throw (exception)
    303344{
    304     if (sock == gInvalidSocket)
     345    if (sock == INVALID_SOCKET)
    305346        THROW_EXCEPTION("has invalid socket");
    306347
     
    313354    throw (exception)
    314355{
    315     if (mSocket == gInvalidSocket)
     356    if (mSocket == INVALID_SOCKET)
    316357        THROW_EXCEPTION("has invalid socket");
    317358
    318359    cf::socket_t sock = mSocket;
    319360
    320     mSocket = gInvalidSocket;
     361    mSocket = INVALID_SOCKET;
    321362
    322363    return sock;
    323364}
    324365
    325 cf::void_t cf::network::tcp::send(const cf::bin & in)
     366cf::void_t cf::network::tcp::send(const cf::bin & in) const
    326367    throw (cf::exception)
    327368{
     
    337378}
    338379
    339 cf::void_t cf::network::tcp::receive(cf::bin & out)
     380cf::void_t cf::network::tcp::receive(cf::bin & out) const
    340381    throw (cf::exception)
    341382{
     
    364405}
    365406
    366 cf::bin cf::network::tcp::receive(const cf::int32_t size)
     407cf::bin cf::network::tcp::receive(const cf::int32_t size) const
    367408    throw (cf::exception)
    368409{
     
    375416}
    376417
    377 cf::bin cf::network::tcp::receive()
     418cf::bin cf::network::tcp::receive() const
    378419    throw (cf::exception)
    379420{
     
    396437cf::void_t cf::network::tcp::getOption(const cf::int32_t optname,
    397438                                       cf::void_t * optval,
    398                                        cf::int32_t * optlen)
     439                                       cf::int32_t * optlen) const
    399440    throw (cf::exception)
    400441{
     
    416457cf::void_t cf::network::tcp::setOption(const cf::int32_t optname,
    417458                                       const cf::void_t * optval,
    418                                        const cf::int32_t optlen)
     459                                       const cf::int32_t optlen) const
    419460    throw (cf::exception)
    420461{
     
    434475}
    435476
    436 cf::void_t cf::network::tcp::setNonBlocking(const cf::bool_t flag)
    437 {
    438 #ifdef _ON_WINDOWS
    439     cf::ulong_t mode = flag ? 1 : 0;
    440     ioctlsocket(mSocket, FIONBIO, &mode);
    441 #else
    442     cf::int32_t mode = fcntl(mSocket, F_GETFL, 0);
    443 
    444     if (flag)   mode |=  O_NONBLOCK;
    445     else        mode &= ~O_NONBLOCK;
    446 
    447     fcntl(mSocket, F_SETFL, mode);
    448 #endif
    449 }
    450 
    451477cf::void_t cf::network::tcp::setTimeout(const cf::int32_t seconds)
    452478{
     479    setNonBlocking(mSocket, seconds > 0 /*? true : false*/);
    453480    mTimeout = seconds;
     481}
     482
     483cf::network::host cf::network::tcp::peer() const
     484    throw (cf::exception)
     485{
     486    try
     487    {
     488        return getSocketNameFromFunction(mSocket, getpeername);
     489    }
     490    catch (cf::exception & e)
     491    {
     492        FORWARD_EXCEPTION(e);
     493    }
     494}
     495
     496cf::network::host cf::network::tcp::local() const
     497    throw (cf::exception)
     498{
     499    try
     500    {
     501        return getSocketNameFromFunction(mSocket, getsockname);
     502    }
     503    catch (cf::exception & e)
     504    {
     505        FORWARD_EXCEPTION(e);
     506    }
    454507}
    455508
Note: See TracChangeset for help on using the changeset viewer.