LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Blogs > rainbowsally
User Name
Password

Notices


Rate this Entry

lqNetDog Addon For Experimenters

Posted 01-24-2013 at 03:14 PM by rainbowsally
Updated 01-24-2013 at 03:18 PM by rainbowsally

lqNetDog Addon For Experimenters

Today's feature is
  • An addon for netdog-v1.2 to get and set connection properties.
  • Setting the blocking timout for the receiver (ans).

Remember, 'ans' (accept) needs to be online to receive the 'orig'inating connection, just like with a phone. Someone has to be there to accept the call or you'll never 'connect'.

We're currently simplifying sockets by combining two or three related functions in a single call using a common struct we call 'pobj', the pointer to the object, which is done implicitly in C++ but which we do explicitly for the sake of 'genericity'. I.e., it's more reusable.

Conversion to a C++ class is simple. 'pobj' *IS* 'this' in C++. It's not as easy to convert from C++ to other forms because much of the interconnection between related parts is done by encoding (called 'mangling') the names thus making the compiler happy but which is nearly impossible to predict* if you try to guess at a C++ name from, say, assembler.

----------
* re. predict.

Name lengths are easy, but the type codes in parameter lists will throw you sometimes. Here's
netdog_delete(netdog_t** &pobj) as shown with 'objdump -d ans'.

_Z13netdog_deletePP8netdog_t

_Z = function, 13 letters in the first part of the name (not a member of a class so no additional parts), PP = '**', and 8 letters in the type, which is a 'netdog_t'.

But take a look at the encodings for builtin types. A 'Pc' is char* and PKc is 'const char*' which are fairly intuitive, but here's
_Z21netdog_getReceiveSizeP8netdog_tPj

What's a Pj? What's a 'j' for that matter? (compare the declaration of netdog_getReceiveSize() in the header to find out. :-)

Anyway...

-----------

If you got the files from our previous experiment here
http://www.linuxquestions.org/questi...ack-box-35281/
you can add stuff like this to get a quick idea of what you can do and how to do it with simple code experiments like this.

Code:
  // added to orig.cpp
  ok = pobj != 0;
  ok &= netdog_request(pobj); // does "connect" internally
  
  int i;
  ok &= netdog_getTCPMaxSegmentSize(pobj, &i);
  
  if(ok)
    printf("TCPMaxSementSize = %d\n", i);
  else
  {
    printf("Woops!\n");
    exit(1);
  }
I knew I saw that number somewhere before. (tracing netcat!)

And in ans.cpp you can set the receive timeout.

[This is great news for the lqMiniTerm as a socket communicator terminal because we now no longer need the non-blocking flag set (and so a netdog-v1.3 is in the offing!).]

The loop timeout can be set by the connection.

Here's an example of the timeout popping out non-byte counts every one second so you can see it cycling.

Code:
  struct timeval t;
  bool ok = true;  // presumably
  ok &= netdog_getReceiveTimeout(pobj, &t); // for fun and it clears the tv_usec field
  t.tv_sec = 1;
  ok &= netdog_setReceiveTimeout(pobj, t);
  //ok &= netdog_getReceiveTimeout(pobj, &t);
run 'xterm &' and type in 'ans'.
it will wait for a connection.
In your main terminal type 'orig'.

The mystery size of TCP segments will display and you'll be sitting there while both apps wait for you to type something into the 'orig'inator of the connection.

Only the ans side will be timing out and showing that '-1' bytes were received, indicating that there was nothing received at all. Not even zero bytes.

Here's netdog_props.cpp and .h which can go into the netdog-v1.2 folder along side the other netdog files.

file: netdog-v1.2/netdog_props.cpp
purpose: source file
Code:
#include "netdog_props.h"
#include "netdog.h"
#include <string.h> // memset()
#include <netinet/tcp.h> // SOL_TCP

bool netdog_setPermitRouteOnOff(netdog_t* pobj, bool tf)
{
  int val = !tf;
  bool ok = 
      setsockopt(pobj->rx_fd, SOL_SOCKET, SO_DONTROUTE, &val, sizeof(val)) == 0;
  return ok ? true : false;
}

bool netdog_setKeepAliveOnOff(netdog_t* pobj, bool tf)
{
  int val = tf != 0;
  bool ok;
  ok = 
      setsockopt(pobj->rx_fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == 0;
  return ok ? true : false;
}

bool netdog_setShareAddressOnOff(netdog_t* pobj, bool tf)
{
  int val = tf != 0;
  bool ok;
  ok = 
      setsockopt(pobj->rx_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) == 0;
  return ok ? true : false;
}

bool netdog_setReceiveSize(netdog_t* pobj, int bytes)
{
  bool ok = 
  setsockopt(pobj->rx_fd, SOL_SOCKET, SO_RCVBUF, &bytes, sizeof(bytes)) == 0;
  return ok ? true : false;
}

bool netdog_getReceiveSize(netdog_t* pobj, size_t* pbytes)
{
  int val = 0;
  socklen_t size=sizeof(val);
  bool ok =
      getsockopt(pobj->rx_fd, SOL_SOCKET, SO_RCVBUF, &val, &size) == 0;
  *pbytes = size;
  return ok ? true : false;
}

bool netdog_setSendSize(netdog_t* pobj, int bytes)
{
  bool ok = 
      setsockopt(pobj->rx_fd, SOL_SOCKET, SO_SNDBUF, &bytes, sizeof(bytes)) == 0;
  return ok ? true : false;
}

bool netdog_getSendSize(netdog_t* pobj, size_t* pbytes)
{
  int val = 0;
  socklen_t size=sizeof(val);
  bool ok = 
  getsockopt(pobj->rx_fd, SOL_SOCKET, SO_SNDBUF, &val, &size) == 0;
  
  *pbytes = val;
  return ok ? true : false;
}

bool netdog_setMinReceive(netdog_t* pobj, int bytes)
{
  int val = 0;
  bool ok = 
      setsockopt(pobj->rx_fd, SOL_SOCKET, SO_RCVLOWAT, &val, sizeof(val)) == 0;
  return ok ? true : false;
}

bool netdog_getMinReceive(netdog_t* pobj, size_t* pbytes)
{
  int val = 0;
  socklen_t size=sizeof(val);
  bool ok = 
  getsockopt(pobj->rx_fd, SOL_SOCKET, SO_RCVLOWAT, &val, &size) == 0;
  
  *pbytes = val;
  return ok;
}

bool netdog_setMinSend(netdog_t* pobj, int bytes) 
// Not yet implemented in Linux ???
{
  bool ok = 
  setsockopt(pobj->rx_fd, SOL_SOCKET, SO_SNDLOWAT, &bytes, sizeof(bytes)) == 0;
  return ok ? true : false;
}

bool netdog_getMinSend(netdog_t* pobj, size_t* pbytes)
{
  int val = 0;
  socklen_t size=sizeof(val);
  bool ok = 
  getsockopt(pobj->rx_fd, SOL_SOCKET, SO_SNDLOWAT, &val, &size) == 0;  
  *pbytes = val;
  return ok ? true : false;
}

bool netdog_setReceiveTimeout(netdog_t* pobj, struct timeval val)
{
  bool ok = 
      setsockopt(pobj->rx_fd, SOL_SOCKET, SO_RCVTIMEO, &val, sizeof(val)) == 0;
  return ok ? true : false;
}

bool netdog_getReceiveTimeout(netdog_t* pobj, struct timeval* ptime)
{
  struct timeval val;
  memset(&val, 0, sizeof(val));
  socklen_t size=sizeof(val);
  bool ok = 
  getsockopt(pobj->rx_fd, SOL_SOCKET, SO_RCVTIMEO, &val, &size) == 0;  
  *ptime = val;
  return ok ? true : false;
}

bool netdog_setSendTimeout(netdog_t* pobj, struct timeval val) 
{
  bool ok = 
      setsockopt(pobj->rx_fd, SOL_SOCKET, SO_SNDTIMEO, &val, sizeof(val)) == 0;
  return ok ? true : false;
}

bool netdog_getSendTimeout(netdog_t* pobj, struct timeval* ptime)
{
  struct timeval val;
  memset(&val, 0, sizeof(val));
  socklen_t size=sizeof(val);
  bool ok = 
  getsockopt(pobj->rx_fd, SOL_SOCKET, SO_SNDTIMEO, &val, &size) == 0;
  *ptime = val;
  return ok ? true : false;
}

bool netdog_getType(netdog_t* pobj, int* pnetwork_type)
{
  int val = 0;
  socklen_t size=sizeof(val);
  bool ok = 
      getsockopt(pobj->rx_fd, SOL_SOCKET, SO_TYPE, &val, &size) == 0;
  *pnetwork_type = val;
  return ok ? true : false;
}

// possible alias getTTLHops()
bool netdog_getTTL(netdog_t* pobj, int* phops)
{
  int val = 0;
  socklen_t size=sizeof(val);
  bool ok;
  if ( pobj->domain == PF_INET) // namespace to type: IPv4
    ok = getsockopt(pobj->rx_fd, SOL_IP, IP_TTL, &val, &size) == 0;
  else if ( pobj->domain == PF_INET6 ) // namespace to type: IPv6
    ok = getsockopt(pobj->rx_fd, SOL_IPV6, IPV6_UNICAST_HOPS, &val, &size) == 0;
  *phops = val;
  return ok ? true : false;
}

// possible alias setTTLHops()
bool netdog_setTTL(netdog_t* pobj, int *phops)
{
  int val = 0;
  bool ok;
  if ( pobj->domain == PF_INET) // namespace to type: IPv4
    ok = setsockopt(pobj->rx_fd, SOL_IP, IP_TTL, &val, sizeof(val)) == 0;
  else if ( pobj->domain == PF_INET6 ) // namespace to type: IPv6
    ok = setsockopt(pobj->rx_fd, SOL_IPV6, IPV6_UNICAST_HOPS, &val, sizeof(val)) == 0;
  return ok ? true : false;
}


bool netdog_getError(netdog_t* pobj, int *perr)
{
  int val = 0;
  socklen_t size=sizeof(val);
  bool ok = 
      getsockopt(pobj->rx_fd, SOL_SOCKET, SO_ERROR, &val, &size) == 0;
  *perr = val;
  return ok ? true : false;
}

// STREAMS ONLY
bool netdog_getTCPMaxSegmentSize(netdog_t* pobj, int* psegsize)
{
  int val = 0;
  socklen_t size=sizeof(val);
  bool ok = 
      getsockopt(pobj->rx_fd, SOL_TCP, TCP_MAXSEG, &val, &size) == 0;
  *psegsize = val;
  return ok ? true : false;
}

bool netdog_setTCPMaxSegmentSize(netdog_t* pobj, int bytes)
{
  bool ok = 
  setsockopt(pobj->rx_fd, SOL_TCP, TCP_MAXSEG, &bytes, sizeof(bytes)) == 0;
  return ok ? true : false;
}

bool netdog_getTCPDelayOnOff(netdog_t* pobj, bool *tf)
{
  socklen_t size = sizeof(*tf);
  bool ok = 
      getsockopt(pobj->rx_fd, SOL_TCP, TCP_NODELAY, &tf, &size) == 0;
  return ok ? true : false;
}

bool netdog_setTCPDelayOnOff(netdog_t* pobj, bool tf)
{
  int val = tf;
  bool ok = 
      setsockopt(pobj->rx_fd, SOL_TCP, TCP_NODELAY, &val, sizeof(val)) == 0;
  return ok ? true : false;
}

file: netdog-v1.2/netdog_props.h
purpose: source file
Code:
// netdog_props.h - template created with new.header

#ifndef netdog_props_h
#define netdog_props_h

/*
 *  network types: 
 *    PF_INET   // IPv4
 *    PF_INET6  // IPv6
 *  
 *  protocols:
 *    SOCK_STREAM // tc/ip - receive when ready
 *    SOCK_DGRAM  // udp - receive now or lose the packet
 * 
 *  IPv6 stuff usually just has a '6' appended to the name.  If you compile, at least 
 *  initially, with g++ the error checking will tell you when you're using the wrong 
 *  type.
 * 
 *  IPv4: get host by address
 *    int size = sizeof(inet->sin_addr.s_addr);  
 *    struct hostent *host = gethostbyaddr(addr, size, PF_INET);
 *  
 *  IPv4: get host by name
 *    struct hostent *host = gethostbyname(Name);
 * 
 *  
 *  IPv4: get socket optiions
 *    int ret;
 *    socklen_t size=sizeof(val);
 *    ok = 0 == getsockopt(fd, SOL_SOCK, so_flag, &ret, &size;
 * 
 *  IPv4: set socket optiions
 *    int newval = <value>;
 *    ok = 0 == setsockopt(fd, SOL_SOCK, so_flag, &newval, sizeof(int);
 * 
 *  so_flags with SOL_SOCK:
 *  SO_DONTROUTE  // boolean integer, -Logic
 *  SO_KEEPALIVE  // boolean inteter
 *  SO_REUSEADDR  // boolean integer
 *  
 *  SO_RCVBUF   // size of receive buffer
 *  SO_SNDBUF   // size of send buffer
 *  SO_RCVLOWAT // min receive
 *  SO_SNDLOWAT // min send
 *  SO_RCVTIMEO // receive timeout value
 *  SO_SNDTIMEO // send timeout value
 *  SO_TYPE     // e.g., ipv4, ipv6
 *  
 *  with SOL_SOCK:
 *  IP_TTL            // total hops
 *  
 *  with SOL_IPV6
 *  IPV6_UNICAST_HOPS // hops for ipv6
 *  
 *  with SOL_TCP
 *  TCP_MAXSEG  // tcp max segment size
 *  TCP_NODELAY // 
 */

bool netdog_setPermitRouteOnOff(netdog_t* pobj, bool tf); // no getter
bool netdog_setKeepAliveOnOff(netdog_t* pobj, bool tf); // no getter
bool netdog_setShareAddressOnOff(netdog_t* pobj, bool tf); // no getter

bool netdog_setReceiveSize(netdog_t* pobj, int bytes);
bool netdog_getReceiveSize(netdog_t* pobj, size_t* pbytes);

bool netdog_setSendSize(netdog_t* pobj, int bytes);
bool netdog_getSendSize(netdog_t* pobj, size_t* pbytes);

bool netdog_setMinReceive(netdog_t* pobj, int bytes);
bool netdog_getMinReceive(netdog_t* pobj, size_t* pbytes);

bool netdog_setMinSend(netdog_t* pobj, int bytes);
bool netdog_getMinSend(netdog_t* pobj, size_t* pbytes);

bool netdog_setReceiveTimeout(netdog_t* pobj, struct timeval val);
bool netdog_getReceiveTimeout(netdog_t* pobj, struct timeval* ptime);

bool netdog_setSendTimeout(netdog_t* pobj, struct timeval val);
bool netdog_getSendTimeout(netdog_t* pobj, struct timeval* ptime);

bool netdog_getType(netdog_t* pobj, int* pnetwork_type); // 0 = IPv4, 1 = IPv6

// possible alias getTTLHops()
bool netdog_getTTL(netdog_t* pobj, int* phops);

// possible alias setTTLHops()
bool netdog_setTTL(netdog_t* pobj, int *phops);

bool netdog_getError(netdog_t* pobj, int *perr);

// STREAMS ONLY
bool netdog_getTCPMaxSegmentSize(netdog_t* pobj, int* psegsize);
bool netdog_setTCPMaxSegmentSize(netdog_t* pobj, int bytes); // this is almost certainly wrong
bool netdog_getTCPDelayOnOff(netdog_t* pobj, bool *tf);
bool netdog_setTCPDelayOnOff(netdog_t* pobj, bool tf);

#endif // netdog_props_h
Not all of these functions have been tested yet and there are likely to be some bugs (inherited from the source of half of these functions which was a terrible mess), but there you go.

And easily reimplemented in your own sockets toolkit if you have one brewing.

- The Computer Mad Science Team

:-)
Posted in Uncategorized
Views 831 Comments 0
« Prev     Main     Next »
Total Comments 0

Comments

 

  



All times are GMT -5. The time now is 07:05 AM.

Main Menu
Advertisement
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration