Advertisement
Guest User

socket code

a guest
Apr 22nd, 2012
509
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.67 KB | None | 0 0
  1. #include <stdbool.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <signal.h>
  10. #include <stdint.h>
  11. #include <stdarg.h>
  12.  
  13. //on success, returns a non-negative socket file descriptor,
  14. //and sets *clientaddr if clientaddr is not NULL
  15. //on failure, returns a negative error code, and errno is set accordingly
  16. int forklisten(uint16_t port, uint32_t* clientaddr) {
  17.         //open socket
  18.         int sock = socket(AF_INET, SOCK_STREAM, 0);
  19.         if(sock < 0)
  20.                 return -1;
  21.  
  22.         //fill serv_addr_in struct
  23.         struct sockaddr_in srvaddr;
  24.         srvaddr.sin_family = AF_INET;
  25.         srvaddr.sin_port = htons(port); //listen on the given port
  26.         srvaddr.sin_addr.s_addr = htonl(INADDR_ANY); //listen on any address
  27.  
  28.         //bind the socket
  29.         if(bind(sock, (struct sockaddr*) &srvaddr, sizeof(srvaddr)) < 0)
  30.                 return -2;
  31.  
  32.         //listen for new connections on the socket
  33.         //the backlog value of 5 indicates that 5 outstanding connections should be allowed to remain in the listening queue
  34.         if(listen(sock, 5) < 0)
  35.                 return -3;
  36.  
  37.         //ignore child process termination
  38.         signal(SIGCHLD, SIG_IGN);
  39.  
  40.         int chldsock;
  41.         //the parent process will forever stay in this loop
  42.         while(true) {
  43.                 //wait for a new connection and accept it
  44.                 struct sockaddr_in cliaddr;
  45.                 unsigned int cliaddrlen = sizeof(cliaddr);
  46.                 if((chldsock = accept(sock, (struct sockaddr*) &cliaddr, &cliaddrlen)) < 0)
  47.                         return -4;
  48.  
  49.                 //fork off a child
  50.                 switch(fork()) {
  51.                 case -1:
  52.                         //the fork() failed, so clean up the sockets and fail
  53.                         close(chldsock);
  54.                         close(sock);
  55.                         return -5;
  56.                 case 0:
  57.                         //we're the child process, so we don't need sock
  58.                         close(sock);
  59.  
  60.                         //set the client address
  61.                         if(clientaddr && cliaddrlen)
  62.                                 *clientaddr = ntohl(cliaddr.sin_addr.s_addr);
  63.  
  64.                         return chldsock;
  65.                 default:
  66.                         //we're the parent process, so we don't need chldsock
  67.                         close(chldsock);
  68.                 }
  69.         }
  70. }
  71.  
  72. inline int fdputs(const char* str, int fd) {
  73.         return write(fd, str, strlen(str));
  74. }
  75.  
  76. //returns the number of bytes written to the fd on success
  77. //on failure, returns a negative error number and sets errval accordingly
  78. int fdprintf(int fd, const char *format, ...) {
  79.         //basically GNU asprintf
  80.         const unsigned buf_size = 16;
  81.         char* buf = (char*) malloc(sizeof(char) * buf_size);
  82.         if(!buf)
  83.                 return -1;
  84.  
  85.         va_list vl;
  86.  
  87.         //first, try to vsnprintf to a buffer of length 16
  88.         va_start(vl, format);
  89.         unsigned len = vsnprintf(buf, buf_size, format, vl);
  90.         va_end(vl);
  91.  
  92.         //if that wasn't enough, allocate more memory and try again
  93.         if (len >= buf_size) {
  94.                 buf = (char*) realloc(buf, sizeof(char) * (len + 1));
  95.                 if(!buf)
  96.                         return -1;
  97.  
  98.                 va_start(vl, format);
  99.                 vsnprintf(buf, len + 1, format, vl);
  100.                 va_end(vl);
  101.         }
  102.  
  103.         //output buf to the socket
  104.         int result = fdputs(buf, fd);
  105.  
  106.         //free the buffer
  107.         free(buf);
  108.  
  109.         return result;
  110. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement