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

Revision 389, 7.1 KB (checked in by trnewman, 15 years ago)

Added DSA CBR reference implementation.
Added simple python example application for DSA CBR.
Added GNUradio python application that uses CROSS and the DSA CBR.

Fixed several bugs in the socket interface.

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