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

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

Added a new CreateClientSocket? function, using the new RemoteComponent? struct
type, to replace the old ClientSocket? function. Note that the old function is
left in until the new stuff gets tested and reviewed.

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.
81 */
82void
83CreateClientSocket(struct RemoteComponent* serverInfo)
84{
85    if(serverInfo == NULL)
86        ERROR(1, "CreateClientSocket received null struct pointer.\n");
87
88    struct hostent *server = gethostbyname(serverInfo->serverName.c_str());
89    if(server == NULL)
90        ERROR(1, "No server found by that hostname.");
91       
92    memcpy(serverInfo, server, sizeof(struct hostent));
93
94    serverInfo->socketFD = socket(AF_INET, SOCK_STREAM, 0);
95    if(serverInfo->socketFD < 0)
96        ERROR(1, "Error opening socket");
97
98    struct sockaddr_in serv_addr;
99    memset((void *) &serv_addr, 0, sizeof(serv_addr));
100    serv_addr.sin_family = AF_INET;
101    serv_addr.sin_port = htons(serverInfo->serverPort);
102    memcpy((char *) &serv_addr.sin_addr.s_addr, (char *) server->h_addr, \
103            server->h_length);
104
105    if(connect(serverInfo->socketFD, (struct sockaddr *) &serv_addr, \
106            sizeof(serv_addr)) < 0)
107        ERROR(1, "Error connecting to remote socket.");
108}
109
110   
111/* TODO I'm fairly certain this function is unnecessary, see function below for more details...
112int32_t
113SendMessage(int32_t socketFD, char* message)
114{
115     
116    // TODO explain this. What, exactly, does the below line do and how does it
117    // affect the rest of the function?
118    strcat(message, "\0000");
119
120    ssize_t numSentBytes = send(socketFD, message, (strlen(message) + 1), 0);
121    if(numSentBytes < 0) {
122        ERROR(1, "Error sending to server.");
123    }
124    else if(numSentBytes == 0) {
125        LOG("socket_comm::SendMessage - Server closed the socket.\n");
126    }
127   
128    return numSentBytes;
129}
130*/
131
132// TODO this function is here to handle calls to send const char* messages. Note
133// that the std::string.c_str() function auto-appends a null character at the
134// end of the cstring, so the strcat function call in the previous function
135// isn't necessary here... I think... although I still don't really understand
136// what exactly that call is for.
137int32_t
138SendMessage(int32_t socketFD, const char* message)
139{
140    ssize_t numSentBytes = send(socketFD, message, (strlen(message) + 1), 0);
141    if(numSentBytes < 0) {
142        ERROR(1, "Error sending to server.");
143    }
144    else if(numSentBytes == 0) {
145        LOG("socket_comm::SendMessage - Server closed the socket.\n");
146    }
147   
148    return numSentBytes;
149}
150
151
152// TODO This function is currently returning 1... always... is this necessary?
153// If we want a fail/success return type, then why aren't we ever returning a
154// failure?
155int32_t
156GetParameter(int32_t socketFD, struct Parameter pList[], \
157        struct CE_Info *ce_info)
158{
159    char buffer[256];
160    memset(buffer, 0, 256);
161
162    ReadMessage(socketFD, buffer);
163    ce_info->numParameters = atoi(buffer);
164    LOG("socket_comm::GetParameter - Number of parameters: %d\n", \
165            ce_info->numParameters);
166   
167    for(size_t i = 0; i < ce_info->numParameters; i++) {
168        memset(buffer, 0, 256);
169        ReadMessage(socketFD, buffer);
170        LOG("socket_comm::GetParameter - Name: %s\n", buffer);
171        pList[i].name = std::string(buffer);
172   
173        memset(buffer, 0, 256);
174        ReadMessage(socketFD, buffer);
175        LOG("socket_comm::GetParameter - Units: %s\n", buffer);
176        pList[i].units = std::string(buffer);
177
178        memset(buffer, 0, 256);
179        ReadMessage(socketFD, buffer);
180        LOG("socket_comm::GetParameter - Min: %s\n", buffer);
181        pList[i].min = atof(buffer);
182   
183        memset(buffer, 0, 256);
184        ReadMessage(socketFD, buffer);
185        LOG("socket_comm::GetParameter - Max: %s\n", buffer);
186        pList[i].max = atof(buffer);
187   
188        memset(buffer, 0, 256);
189        ReadMessage(socketFD, buffer);
190        LOG("socket_comm::GetParameter - Step: %s\n", buffer);
191        pList[i].step = atof(buffer);
192   
193        memset(buffer, 0, 256);
194        ReadMessage(socketFD, buffer);
195        LOG("socket_comm::GetParameter - Value: %s\n", buffer);
196        pList[i].value = atof(buffer);
197    }
198
199    return 1;
200}
201
202
203// TODO if we are just returing fail/success here, then why not return a bool
204// instead of an entire 32 bit integer?  Seems wasteful.
205int32_t
206GetRequest(int32_t socketFD, struct Parameter pList[], struct CE_Info *ce_info)
207{
208    char buffer[256];
209    memset(buffer, 0, 256);
210   
211    ReadMessage(socketFD, buffer);
212
213    if(strcmp(buffer, "val") != 0) {
214        LOG("socket_comm::GetRequest - Unexpected control data received.\n\n");
215        return 0;
216    }
217
218    LOG("socket_comm::GetRequest - Getting parameters.\n\n");
219    GetParameter(socketFD, pList, ce_info);
220
221    return 1;
222}
223
224
225int32_t
226AcceptTCPConnection(int32_t serverSock)
227{
228    struct sockaddr_in echoClientAddr;
229
230    uint32_t clientLength = sizeof(echoClientAddr);
231
232    int32_t clientSocket = accept(serverSock, NULL, NULL);
233    if(clientSocket < 0)
234        ERROR(1, "Could establish connection with client socket.\n");
235   
236    LOG("Handling client %s\n", inet_ntoa(echoClientAddr.sin_addr));
237
238    return clientSocket;
239}
240
241
242int32_t
243CreateTCPServerSocket(uint16_t port)
244{
245    struct sockaddr_in echoServerAddr;
246
247    int32_t localSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
248    if (localSocket < 0)
249        ERROR(1, "socket() failed\n");
250     
251    /* Construct the local address structure */
252    memset(&echoServerAddr, 0, sizeof(echoServerAddr));
253    echoServerAddr.sin_family = AF_INET;
254    echoServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
255    echoServerAddr.sin_port = htons(port);
256
257    /* Bind to the local address */
258    if(bind(localSocket, (struct sockaddr *) &echoServerAddr, \
259            sizeof(echoServerAddr)) < 0)
260        ERROR(1, "bind() failed\n");
261
262    /* Mark the socket so it will listen for incoming connections */
263    if(listen(localSocket, 5) < 0)
264        ERROR(1, "listen() failed\n");
265
266    return localSocket;
267}
268
Note: See TracBrowser for help on using the browser.