WPILibC++  trunk
SocketServerStreamProvider.cpp
1 /*
2  * SocketServerStreamProvider.cpp
3  *
4  * Created on: Sep 27, 2012
5  * Author: Mitchell Wills
6  */
7 
8 #include "networktables2/stream/SocketServerStreamProvider.h"
9 #include "networktables2/stream/FDIOStream.h"
10 #include "networktables2/util/IOException.h"
11 
12 #include <strings.h>
13 #include <cstring>
14 #include <errno.h>
15 #ifdef _WRS_KERNEL
16 #include <inetLib.h>
17 #include <selectLib.h>
18 #include <sockLib.h>
19 #include <taskLib.h>
20 #include <usrLib.h>
21 #include <ioLib.h>
22 #include <netinet/in.h>
23 #include <netinet/tcp.h>
24 #else
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 #ifdef WIN32
30 #include <windows.h>
31 #include <winsock.h>
32 #include <winsock2.h>
33 #include <wininet.h>
34 #include <ws2tcpip.h>
35 #else
36 #include <sys/socket.h>
37 #include <sys/un.h>
38 #include <netinet/in.h>
39 #include <netinet/tcp.h>
40 #endif
41 #endif
42 
43 #ifndef _WRS_KERNEL
44 #define ERROR -1
45 #endif
46 
47 #if defined(WIN32) || defined(_WRS_KERNEL)
48 typedef int addrlen_t;
49 #else
50 typedef socklen_t addrlen_t;
51 #endif
52 
53 
54 SocketServerStreamProvider::SocketServerStreamProvider(int port){
55  struct sockaddr_in serverAddr;
56  int sockAddrSize = sizeof(serverAddr);
57  memset(&serverAddr, 0, sockAddrSize);
58 
59 #ifdef _WRS_KERNEL
60  serverAddr.sin_len = (u_char)sockAddrSize;
61 #endif
62  serverAddr.sin_family = AF_INET;
63  serverAddr.sin_port = htons(port);
64  serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
65 
66  if ((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) == ERROR)
67  {
68  throw IOException("Error creating server socket", errno);
69  }
70 
71  // Set the TCP socket so that it can be reused if it is in the wait state.
72  int reuseAddr = 1;
73  setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseAddr, sizeof(reuseAddr));
74 
75  // Bind socket to local address.
76  if (bind(serverSocket, (struct sockaddr *)&serverAddr, sockAddrSize) == ERROR)
77  {
78  ::close(serverSocket);
79  throw IOException("Could not bind server socket", errno);
80  }
81 
82  if (listen(serverSocket, 1) == ERROR)
83  {
84  ::close(serverSocket);
85  throw IOException("Could not listen on server socket", errno);
86  }
87 }
88 SocketServerStreamProvider::~SocketServerStreamProvider(){
89  close();
90 }
91 
92 
94  struct timeval timeout;
95  // Check for a shutdown once per second
96  while (true)
97  {
98  fd_set fdSet;
99 
100  FD_ZERO(&fdSet);
101  FD_SET(serverSocket, &fdSet);
102  timeout.tv_sec = 1;
103  timeout.tv_usec = 0;
104  int select_result = select(FD_SETSIZE, &fdSet, NULL, NULL, &timeout);
105  if ( select_result < 0)
106  return NULL;
107 
108  if (FD_ISSET(serverSocket, &fdSet))
109  {
110  struct sockaddr clientAddr;
111  memset(&clientAddr, 0, sizeof(struct sockaddr));
112  addrlen_t clientAddrSize = sizeof(clientAddr);
113  int connectedSocket = ::accept(serverSocket, &clientAddr, &clientAddrSize);
114  if (connectedSocket == ERROR)
115  return NULL;
116 
117  return new FDIOStream(connectedSocket);
118  }
119 
120 
121  }
122  return NULL;
123 }
124 
126  ::close(serverSocket);
127 }