root/vtcross/trunk/src/lib/socketcomm/socketcomm.cpp @ 186

Revision 186, 7.6 KB (checked in by bhilburn, 15 years ago)

Made the remotecomponent struct public since information hiding doesn't
make any sense here, removed unneeded info from it, worked on a couple
of policy engine functions to be smart about start-up connections.

Line 
1/* Virginia Tech Cognitive Radio Open Source Systems
2 * Virginia Tech, 2009
3 *
4 * TODO LICENSE INFORMATION GOES HERE
5 */
6
7/* TODO DESCRIPTION OF FILE.
8 */
9
10
11#include <arpa/inet.h>
12#include <cstdlib>
13#include <cstring>
14#include <netdb.h>
15#include <netinet/in.h>
16#include <stdint.h>
17#include <string>
18#include <sys/types.h>
19#include <sys/socket.h>
20
21#include "vtcross/common.h"
22#include "vtcross/containers.h"
23#include "vtcross/debug.h"
24#include "vtcross/error.h"
25#include "vtcross/socketcomm.h"
26
27
28// TODO can someone write a description of how this function is operating? I'm
29// not sure I understand why it is making two separate blocking calls to recv
30void
31ReadMessage(int32_t socketFD, char* msgBuffer)
32{
33    ssize_t msgLength = recv(socketFD, msgBuffer, 256, MSG_PEEK);
34
35    size_t i;
36    for(i = 0; i < 256; i++) {
37            if(strcmp(&msgBuffer[i], "\0") == 0)
38            break;
39    }
40
41    msgLength = recv(socketFD, msgBuffer, i + 1, 0);
42    if (msgLength < 0)
43        ERROR(1, "Error reading from socket");
44}
45
46
47int32_t
48ClientSocket(const char* serverName, const char* portNumber)
49{
50    int32_t socketFD;
51    int32_t portNo;
52
53    struct sockaddr_in serv_addr;
54    struct hostent *server;
55   
56    server = gethostbyname(serverName);
57    if(server == NULL)
58        ERROR(1, "No server found by that hostname.");
59
60    portNo = atoi(portNumber);
61
62    socketFD = socket(AF_INET, SOCK_STREAM, 0);
63    if(socketFD < 0)
64        ERROR(1, "Error opening socket");
65
66    memset((void *) &serv_addr, 0, sizeof(serv_addr));
67    serv_addr.sin_family = AF_INET;
68    serv_addr.sin_port = htons(portNo);
69    memcpy((char *) &serv_addr.sin_addr.s_addr, (char *) server->h_addr, \
70            server->h_length);
71
72    if(connect(socketFD, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
73        ERROR(1, "Error connecting to remote socket.");
74
75    return socketFD;
76}
77
78
79/* TODO see notes in socketcomm.h. This function, and the RemoteComponent
80 * struct, need a code review to make sure it is ready to be used rather
81 * than ClientSocket()
82 */
83void
84CreateClientSocket(struct RemoteComponent* serverInfo)
85{
86    if(serverInfo == NULL)
87        ERROR(1, "CreateClientSocket received null struct pointer.\n");
88
89    struct hostent *server = gethostbyname(serverInfo->serverName.c_str());
90    if(server == NULL)
91        ERROR(1, "No server found by that hostname.");
92       
93    serverInfo->socketFD = socket(AF_INET, SOCK_STREAM, 0);
94    if(serverInfo->socketFD < 0)
95        ERROR(1, "Error opening socket");
96
97    struct sockaddr_in serv_addr;
98    memset((void *) &serv_addr, 0, sizeof(serv_addr));
99    serv_addr.sin_family = AF_INET;
100    serv_addr.sin_port = htons(serverInfo->serverPort);
101    memcpy((char *) &serv_addr.sin_addr.s_addr, (char *) server->h_addr, \
102            server->h_length);
103
104    if(connect(serverInfo->socketFD, (struct sockaddr *) &serv_addr, \
105            sizeof(serv_addr)) < 0)
106        ERROR(1, "Error connecting to remote socket.");
107}
108
109   
110/* TODO I'm fairly certain this function is unnecessary, see function below for more details...
111int32_t
112SendMessage(int32_t socketFD, char* message)
113{
114     
115    // TODO explain this. What, exactly, does the below line do and how does it
116    // affect the rest of the function?
117    strcat(message, "\0000");
118
119    ssize_t numSentBytes = send(socketFD, message, (strlen(message) + 1), 0);
120    if(numSentBytes < 0) {
121        ERROR(1, "Error sending to server.");
122    }
123    else if(numSentBytes == 0) {
124        LOG("socket_comm::SendMessage - Server closed the socket.\n");
125    }
126   
127    return numSentBytes;
128}
129*/
130
131// TODO this function is here to handle calls to send const char* messages. Note
132// that the std::string.c_str() function auto-appends a null character at the
133// end of the cstring, so the strcat function call in the previous function
134// isn't necessary here... I think... although I still don't really understand
135// what exactly that call is for.
136int32_t
137SendMessage(int32_t socketFD, const char* message)
138{
139    ssize_t numSentBytes = send(socketFD, message, (strlen(message) + 1), 0);
140    if(numSentBytes < 0) {
141        ERROR(1, "Error sending to server.");
142    }
143    else if(numSentBytes == 0) {
144        LOG("socket_comm::SendMessage - Server closed the socket.\n");
145    }
146   
147    return numSentBytes;
148}
149
150
151// TODO This function is currently returning 1... always... is this necessary?
152// If we want a fail/success return type, then why aren't we ever returning a
153// failure?
154int32_t
155GetParameter(int32_t socketFD, struct Parameter pList[], \
156        struct CE_Info *ce_info)
157{
158    char buffer[256];
159    memset(buffer, 0, 256);
160
161    ReadMessage(socketFD, buffer);
162    ce_info->numParameters = atoi(buffer);
163    LOG("socket_comm::GetParameter - Number of parameters: %d\n", \
164            ce_info->numParameters);
165   
166    for(size_t i = 0; i < ce_info->numParameters; i++) {
167        memset(buffer, 0, 256);
168        ReadMessage(socketFD, buffer);
169        LOG("socket_comm::GetParameter - Name: %s\n", buffer);
170        pList[i].name = std::string(buffer);
171   
172        memset(buffer, 0, 256);
173        ReadMessage(socketFD, buffer);
174        LOG("socket_comm::GetParameter - Units: %s\n", buffer);
175        pList[i].units = std::string(buffer);
176
177        memset(buffer, 0, 256);
178        ReadMessage(socketFD, buffer);
179        LOG("socket_comm::GetParameter - Min: %s\n", buffer);
180        pList[i].min = atof(buffer);
181   
182        memset(buffer, 0, 256);
183        ReadMessage(socketFD, buffer);
184        LOG("socket_comm::GetParameter - Max: %s\n", buffer);
185        pList[i].max = atof(buffer);
186   
187        memset(buffer, 0, 256);
188        ReadMessage(socketFD, buffer);
189        LOG("socket_comm::GetParameter - Step: %s\n", buffer);
190        pList[i].step = atof(buffer);
191   
192        memset(buffer, 0, 256);
193        ReadMessage(socketFD, buffer);
194        LOG("socket_comm::GetParameter - Value: %s\n", buffer);
195        pList[i].value = atof(buffer);
196    }
197
198    return 1;
199}
200
201
202// TODO if we are just returing fail/success here, then why not return a bool
203// instead of an entire 32 bit integer?  Seems wasteful.
204int32_t
205GetRequest(int32_t socketFD, struct Parameter pList[], struct CE_Info *ce_info)
206{
207    char buffer[256];
208    memset(buffer, 0, 256);
209   
210    ReadMessage(socketFD, buffer);
211
212    if(strcmp(buffer, "val") != 0) {
213        LOG("socket_comm::GetRequest - Unexpected control data received.\n\n");
214        return 0;
215    }
216
217    LOG("socket_comm::GetRequest - Getting parameters.\n\n");
218    GetParameter(socketFD, pList, ce_info);
219
220    return 1;
221}
222
223
224int32_t
225AcceptTCPConnection(int32_t serverSock)
226{
227    struct sockaddr_in echoClientAddr;
228
229    uint32_t clientLength = sizeof(echoClientAddr);
230
231    int32_t clientSocket = accept(serverSock, NULL, NULL);
232    if(clientSocket < 0)
233        ERROR(1, "Could not establish connection with client socket.\n");
234   
235    LOG("Handling client %s\n", inet_ntoa(echoClientAddr.sin_addr));
236
237    return clientSocket;
238}
239
240
241int32_t
242CreateTCPServerSocket(uint16_t port)
243{
244    struct sockaddr_in echoServerAddr;
245
246    int32_t localSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
247    if (localSocket < 0)
248        ERROR(1, "socket() failed\n");
249     
250    /* Construct the local address structure */
251    memset(&echoServerAddr, 0, sizeof(echoServerAddr));
252    echoServerAddr.sin_family = AF_INET;
253    echoServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
254    echoServerAddr.sin_port = htons(port);
255
256    /* Bind to the local address */
257    if(bind(localSocket, (struct sockaddr *) &echoServerAddr, \
258            sizeof(echoServerAddr)) < 0)
259        ERROR(1, "bind() failed\n");
260
261    /* Mark the socket so it will listen for incoming connections */
262    if(listen(localSocket, 5) < 0)
263        ERROR(1, "listen() failed\n");
264
265    return localSocket;
266}
267
Note: See TracBrowser for help on using the browser.