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

Revision 195, 6.7 KB (checked in by bhilburn, 15 years ago)

CE_Info didn't make sense anymore since it was really describing the
entire radio; fixed.

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
30//
31// TODO also, it appears that this function can, at maximum, receive 256 bytes
32// without causing a buffer overflow. can someone confirm/deny?
33void
34ReadMessage(int32_t socketFD, char* msgBuffer)
35{
36    ssize_t msgLength = recv(socketFD, msgBuffer, 256, MSG_PEEK);
37
38    size_t i;
39    for(i = 0; i < 256; i++) {
40            if(strcmp(&msgBuffer[i], "\0") == 0)
41            break;
42    }
43
44    msgLength = recv(socketFD, msgBuffer, i + 1, 0);
45    if (msgLength < 0)
46        ERROR(1, "Error reading from socket");
47}
48
49
50int32_t
51ClientSocket(const char* serverName, const char* serverPort)
52{
53    int32_t socketFD;
54    int32_t portNumber;
55
56    struct sockaddr_in serv_addr;
57    struct hostent *server;
58   
59    server = gethostbyname(serverName);
60    if(server == NULL)
61        ERROR(1, "No server found by that hostname.");
62
63    portNumber = atoi(serverPort);
64
65    socketFD = socket(AF_INET, SOCK_STREAM, 0);
66    if(socketFD < 0)
67        ERROR(1, "Error opening socket");
68
69    memset((void *) &serv_addr, 0, sizeof(serv_addr));
70    serv_addr.sin_family = AF_INET;
71    serv_addr.sin_port = htons(portNumber);
72    memcpy((char *) &serv_addr.sin_addr.s_addr, (char *) server->h_addr, \
73            server->h_length);
74
75    if(connect(socketFD, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
76        ERROR(1, "Error connecting to remote socket.");
77
78    return socketFD;
79}
80
81   
82/* TODO I'm fairly certain this function is unnecessary, see function below for more details...
83int32_t
84SendMessage(int32_t socketFD, char* message)
85{
86     
87    // TODO explain this. What, exactly, does the below line do and how does it
88    // affect the rest of the function?
89    strcat(message, "\0000");
90
91    ssize_t numSentBytes = send(socketFD, message, (strlen(message) + 1), 0);
92    if(numSentBytes < 0) {
93        ERROR(1, "Error sending to server.");
94    }
95    else if(numSentBytes == 0) {
96        LOG("socket_comm::SendMessage - Server closed the socket.\n");
97    }
98   
99    return numSentBytes;
100}
101*/
102
103// TODO this function is here to handle calls to send const char* messages. Note
104// that the std::string.c_str() function auto-appends a null character at the
105// end of the cstring, so the strcat function call in the previous function
106// isn't necessary here... I think... although I still don't really understand
107// what exactly that call is for.
108int32_t
109SendMessage(int32_t socketFD, const char* message)
110{
111    ssize_t numSentBytes = send(socketFD, message, (strlen(message) + 1), 0);
112    if(numSentBytes < 0) {
113        ERROR(1, "Error sending to server.");
114    }
115    else if(numSentBytes == 0) {
116        LOG("socket_comm::SendMessage - Server closed the socket.\n");
117    }
118   
119    return numSentBytes;
120}
121
122
123// TODO This function is currently returning 1... always... is this necessary?
124// If we want a fail/success return type, then why aren't we ever returning a
125// failure?
126int32_t
127GetParameter(int32_t socketFD, struct Parameter pList[], \
128        struct Radio_Info *radio_info)
129{
130    char buffer[256];
131    memset(buffer, 0, 256);
132
133    ReadMessage(socketFD, buffer);
134    radio_info->numParameters = atoi(buffer);
135    LOG("socket_comm::GetParameter - Number of parameters: %d\n", \
136            radio_info->numParameters);
137   
138    for(size_t i = 0; i < radio_info->numParameters; i++) {
139        memset(buffer, 0, 256);
140        ReadMessage(socketFD, buffer);
141        LOG("socket_comm::GetParameter - Name: %s\n", buffer);
142        pList[i].name = std::string(buffer);
143   
144        memset(buffer, 0, 256);
145        ReadMessage(socketFD, buffer);
146        LOG("socket_comm::GetParameter - Units: %s\n", buffer);
147        pList[i].units = std::string(buffer);
148
149        memset(buffer, 0, 256);
150        ReadMessage(socketFD, buffer);
151        LOG("socket_comm::GetParameter - Min: %s\n", buffer);
152        pList[i].min = atof(buffer);
153   
154        memset(buffer, 0, 256);
155        ReadMessage(socketFD, buffer);
156        LOG("socket_comm::GetParameter - Max: %s\n", buffer);
157        pList[i].max = atof(buffer);
158   
159        memset(buffer, 0, 256);
160        ReadMessage(socketFD, buffer);
161        LOG("socket_comm::GetParameter - Step: %s\n", buffer);
162        pList[i].step = atof(buffer);
163   
164        memset(buffer, 0, 256);
165        ReadMessage(socketFD, buffer);
166        LOG("socket_comm::GetParameter - Value: %s\n", buffer);
167        pList[i].value = atof(buffer);
168    }
169
170    return 1;
171}
172
173
174// TODO if we are just returing fail/success here, then why not return a bool
175// instead of an entire 32 bit integer?  Seems wasteful.
176int32_t
177GetRequest(int32_t socketFD, struct Parameter pList[], struct Radio_Info *radio_info)
178{
179    char buffer[256];
180    memset(buffer, 0, 256);
181   
182    ReadMessage(socketFD, buffer);
183
184    if(strcmp(buffer, "val") != 0) {
185        LOG("socket_comm::GetRequest - Unexpected control data received.\n\n");
186        return 0;
187    }
188
189    LOG("socket_comm::GetRequest - Getting parameters.\n\n");
190    GetParameter(socketFD, pList, radio_info);
191
192    return 1;
193}
194
195
196int32_t
197AcceptTCPConnection(int32_t serverSock)
198{
199    struct sockaddr_in echoClientAddr;
200
201    uint32_t clientLength = sizeof(echoClientAddr);
202
203    int32_t clientSocket = accept(serverSock, NULL, NULL);
204    if(clientSocket < 0)
205        ERROR(1, "Could not establish connection with client socket.\n");
206   
207    LOG("Handling client %s\n", inet_ntoa(echoClientAddr.sin_addr));
208
209    return clientSocket;
210}
211
212
213int32_t
214CreateTCPServerSocket(uint16_t port)
215{
216    struct sockaddr_in echoServerAddr;
217
218    int32_t localSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
219    if (localSocket < 0)
220        ERROR(1, "socket() failed\n");
221     
222    /* Construct the local address structure */
223    memset(&echoServerAddr, 0, sizeof(echoServerAddr));
224    echoServerAddr.sin_family = AF_INET;
225    echoServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
226    echoServerAddr.sin_port = htons(port);
227
228    /* Bind to the local address */
229    if(bind(localSocket, (struct sockaddr *) &echoServerAddr, \
230            sizeof(echoServerAddr)) < 0)
231        ERROR(1, "bind() failed\n");
232
233    /* Mark the socket so it will listen for incoming connections */
234    if(listen(localSocket, 5) < 0)
235        ERROR(1, "listen() failed\n");
236
237    return localSocket;
238}
239
Note: See TracBrowser for help on using the browser.