GophHub - go4retro/tcpser/src/ip.c


Raw File

    1	#include <sys/types.h>
    2	#include <sys/socket.h>
    3	#include <netinet/in.h>
    4	#include <arpa/inet.h>
    5	#include <netdb.h>
    6	#include <unistd.h>       // for read...
    7	#include <stdlib.h>       // for atoi...
    8	
    9	#include "debug.h"
   10	#include "ip.h"
   11	
   12	const int BACK_LOG = 5;
   13	
   14	int ip_init_server_conn(char *ip, int port) {
   15	  char *ip_addr = NULL;
   16	  int sSocket = 0, on = 0, rc = 0;
   17	  struct sockaddr_in serverName = { 0 };
   18	  char * tmp;
   19	
   20	  LOG_ENTER();
   21	
   22	  // Handle special case ":<port>"
   23	  // Without it, ip_add will be set to port and port will be null
   24	
   25	  if(ip != NULL) {
   26	    if(ip[0] == ':') {
   27	      ip = &ip[1];
   28	    }
   29	    if (strchr(ip, ':') != NULL) {
   30	      ip_addr = strtok(ip, ":");
   31	      tmp = strtok(NULL,":");
   32	      if(tmp != NULL && strlen(tmp) > 0) {
   33	        port = (atoi(tmp));
   34	      }
   35	    } else if(strlen(ip) > 0) {
   36	      port = (atoi(ip));
   37	    }
   38	  }
   39	
   40	  LOG(LOG_DEBUG, "Creating server socket");
   41	
   42	  sSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
   43	  if (-1 == sSocket) {
   44	    ELOG(LOG_FATAL, "Server socket could not be created");
   45	  } else {
   46	
   47	    /*
   48	     * turn off bind address checking, and allow 
   49	     * port numbers to be reused - otherwise
   50	     * the TIME_WAIT phenomenon will prevent 
   51	     * binding to these addresses.
   52	     */
   53	
   54	    on = 1;
   55	
   56	    rc = setsockopt(sSocket, 
   57	                    SOL_SOCKET, 
   58	                    SO_REUSEADDR,
   59	                    (const char *) &on, 
   60	                    sizeof(on)
   61	                   );
   62	    if (-1 == rc) {
   63	      ELOG(LOG_ERROR, "bind address checking could not be turned off");
   64	    }
   65	
   66	    if (ip_addr != NULL && strcmp(ip_addr,"") != 0) { /* changed to strcmp test -04Mar17 gwb */
   67	      LOG(LOG_DEBUG, "Using specified ip address '%s'", ip_addr);
   68	      serverName.sin_addr.s_addr = inet_addr(ip_addr);
   69	    } else {
   70	      serverName.sin_addr.s_addr = htonl(INADDR_ANY);
   71	    }
   72	    serverName.sin_family = AF_INET;
   73	
   74	    /* network-order */
   75	    serverName.sin_port = htons(port);
   76	
   77	    LOG(LOG_DEBUG, "Binding server socket to port %d", port);
   78	    rc = bind(sSocket,
   79	              (struct sockaddr *) &serverName,
   80	              sizeof(serverName)
   81	             );
   82	
   83	    if (-1 == rc) {
   84	      ELOG(LOG_FATAL, "Server socket could not be bound to port");
   85	      sSocket = -1;
   86	    } else {
   87	      LOG(LOG_INFO, "Server socket bound to port");
   88	
   89	      rc = listen(sSocket, BACK_LOG);
   90	      LOG(LOG_INFO, "Server socket listening for connections");
   91	      if (-1 == rc) {
   92	        ELOG(LOG_FATAL, "Server socket could not listen on port");
   93	        sSocket = -1;
   94	      }
   95	    }
   96	  }
   97	  LOG_EXIT();
   98	  return sSocket;
   99	}
  100	
  101	int ip_connect(char *ip) {
  102	  struct sockaddr_in pin;
  103	  struct in_addr cin_addr;
  104	  struct hostent *hp;
  105	  int sd = 0;
  106	  int port = 23;
  107	  char *address;
  108	  char *tmp;
  109	
  110	  LOG_ENTER();
  111	  // TODO Can ip be null? If so, fix.
  112	  address = strtok(ip, ":");
  113	  tmp = strtok(NULL, ":");
  114	  if(tmp != NULL && strlen(tmp) > 0) {
  115	    port = atoi(tmp);
  116	  }
  117	
  118	  LOG(LOG_DEBUG, "Calling %s", ip);
  119	  memset(&pin, 0, sizeof(pin));
  120	
  121	  /* go find out about the desired host machine */
  122	  if((hp = gethostbyname(address)) == 0) {
  123	    // well, not a DNS entry... Treat as IP...
  124	    if(1 != inet_aton(address, &cin_addr)) {
  125	      ELOG(LOG_ERROR, "Host %s was invalid", ip);
  126	      return -1;
  127	    }
  128	  } else {
  129	    cin_addr = *((struct in_addr *)(hp->h_addr));
  130	  }
  131	
  132	  pin.sin_family = AF_INET;
  133	  pin.sin_addr.s_addr = cin_addr.s_addr;
  134	  pin.sin_port = htons(port);
  135	
  136	  /* grab an Internet domain socket */
  137	  if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  138	    ELOG(LOG_ERROR, "could not create client socket");
  139	    return -1;
  140	  }
  141	
  142	  /* connect to PORT on HOST */
  143	  if (connect(sd, (struct sockaddr *)&pin, sizeof(pin)) == -1) {
  144	    ELOG(LOG_ERROR, "could not connect to address");
  145	    return -1;
  146	  }
  147	  LOG(LOG_INFO, "Connection to %s established", ip);
  148	  LOG_EXIT();
  149	  return sd;
  150	}
  151	
  152	int ip_accept(int sSocket) {
  153	  struct sockaddr_in clientName = { 0 };
  154	  socklen_t clientLength = sizeof(clientName);
  155	  int cSocket = -1;
  156	
  157	  LOG_ENTER();
  158	  (void) memset(&clientName, 0, sizeof(clientName));
  159	
  160	  cSocket = accept(sSocket,
  161	                   (struct sockaddr *)&clientName, 
  162	                   &clientLength
  163	                  );
  164	  if (-1 == cSocket) {
  165	    ELOG(LOG_ERROR, "Could not accept incoming connection");
  166	    return -1;
  167	  }
  168	
  169	  if(-1 == getpeername(cSocket,
  170	                        (struct sockaddr *)&clientName, 
  171	                        &clientLength
  172	                       )) {
  173	    ELOG(LOG_WARN, "Could not obtain peer name");
  174	  } else {
  175	    LOG(LOG_INFO, 
  176	        "Connection accepted from %s",
  177	        inet_ntoa(clientName.sin_addr)
  178	       );
  179	  }
  180	  LOG_EXIT();
  181	  return cSocket;
  182	}
  183	
  184	int ip_disconnect(int fd) {
  185	  if(fd > -1)
  186	    close(fd);
  187	  return 0;
  188	}
  189	
  190	int ip_write(int fd, unsigned char *data, int len) {
  191	  log_trace(TRACE_IP_OUT, data, len);
  192	  return write(fd, data, len);
  193	}
  194	
  195	int ip_read(int fd, unsigned char *data, int len) {
  196	  int res;
  197	
  198	  res = recv(fd, data, len, 0);
  199	  if(0 < res)
  200	  	log_trace(TRACE_IP_IN, data, res);
  201	  return res;
  202	}
  203	

Generated by GNU Enscript 1.6.6, and GophHub 1.3.